カテゴリー別アーカイブ: はまりどころ/注意点

update-select文とupdate-for文について

SQLでもっともつまづきやすいupdate-select文というものがある。

select文による結果でupdateするが、その正しいやり方というのを見ると、おそらく誰もが気持ち悪いと思うはず。

SELECT結果でのUPDATE
qa.atmarkit.co.jp/q/98

setでデータを入れるサブクエリ内のSELECT文のwhere句ではなく、updateの更新対象を絞り込むUPDATEのwhere句をしっかり定義しないと、思った通りに動かないことがある...そして、サブクエリ内のwhere句の条件とupdate文のwhere句の条件は往々にして同じような条件になるため、SQLの文法を知らない人が見ると「何で同じような定義を2回しているんだ?」という疑問を持つことになる。更新先の絞り込みをしないと更新元がない時に問題を起こすので、同じような条件を指定しているのだ。これを解決する手段としてpostgresとしてはupdate文にfor文を連結して更新対象と更新結果を出力するselect文を書くことができる。これによりupdate文にselect文のサブクエリを連結せずにスムーズにデータ挿入することが可能になる。

UTF-8のCSVファイルをcatコマンドで連結したら文字化けした!?

以下の様なコードを実行した...。

cat *.csv > convert.csv

出力されたconvert.csvの中身が派手にぶっ壊れている。

もしかしてcatコマンドは古いツールだからUTF-8に対応していないのか?

BOMとかそういうのが悪さしているか?

...色々と考えた結果、

すでにconvert.csvというファイルがあって、
それを*.csvとしてワイルドカードでまとめている、
つまり、マッチポンプっつーか、再入力しているっつーか、
アウトプットファイルがインプットファイルにもなっているため、
壊れていたもよう...。

残念な間違い。

SE戦記@「メール1通しか送ってないのに2通届くんですけど」

Web屋をやっていれば、社内に数えるほどのメール送信システムがあったりするものだ。

 余談だが、LINEとかSkypeとか伝達手段なんかいくらでもあるのに何でメールなんだろう?なんて思うことがある。共通の電信プラットフォームがあれば事足りると思うのだがわざわざメールサーバを立ててビジネスパーソンは日々せわしくメールを送受信している。個人情報がサーバ管理者に拾われるMSのSkypeならともかくLINEなんか韓国の法人なんだから信用できるか!とネトウヨが言うたりするが、それならメールのリレー中に途中経路で盗聴されていないかとか心配したほうがよっぽど重要なんじゃないだろうか?メールサーバのサーバ管理者が悪巧みしているかもしれないということをなぜかメールを使う人は考えない。ふしぎである。自社で管理しているメールサーバならともかく大きな会社でも安価なレンタルサーバで済ましているなんてざらにある。社会的信用がある企業がLINEみたいなのを作る例はあるだろう。skypeもそうだしKDDIも似たようなものを作成していたと思う。でも流行らない。重要なのはセキュリティうんぬんじゃなくて大勢がプラットフォームを使っているか否かということなんだろう。
 そういえば何の意味もないのに、メールを2通に分けて、パスワードをかけたZIPしたデータと、パスワードがかかれたメールが送らられてきたりする。まだ違うメールアドレスから送信したものというなら経路による頭頂は防げるかもしれないが、サーバ管理者や送信者のネットワークが乗っ取られてたら盗聴されるんで、なんにも意味がないのだが…なんでこんな原始的な方法がとられているのだろうか?何度も言うが、セキュリティが守られているかもしれない!という「かもしれない」で行動を起こしてはいけない。車を運転する時は…「轢き殺すかもしれない」で運転してはダメだし逆に「轢き殺さないかもしれない」で運転してもダメ。

--

そんなことより、
ある日のこと私が作成したとあるメール送信システムの不具合が報告された。

「すみません、メールを1通しか予約していないのに2通届いているんです…」
社内のメール送信システムを使う女の子が早口で言った。この人をAとする。
Aさんはイライラを隠しているのがひしひしと感じた。
「そりゃおかしいネ」わたしはとぼけながら、
すぐに送信ログを調べてみたが、メールは1通しか送信していなかった。

1通しか送信していないものが2通送信されるものか。
だいたいなんで2通とどいたとわかるんでしょう?。疑問に思った私は、
「お客様が2通届いたと言ってきたんですか?」とたずねた。

Aさんは答えた「いえ、私に2通とどいているんです」…なにそれ。
なんで自分に送っているのかしら。状況がつかめない。話を聞いてみると、
内容を確認するために、自分宛てにBCCでメールをクライアントに送信しているとのことだ。
用心深いんだか、システムを信じていないのか、面倒くさい感じ、、。

繰り返しになるが1通しか送っていないのに2通届くなんてあるんだろうか?

メールの受信が2回動いている?そんなバグがあるんだろうか。
そんなことは設定ミス/転送ミスでならあるかもしれないが運用はずっと前からしていて、
設定はいじっていないのでその線は消える。

メンテ不足によりメールプログラムがご動作しているってわけでもないようだ。

Aさんのメーラを確認させてもらったところ、たしかに2つBCCのメールがとどている。

さて、何が問題なんだろう???

答えの前に…

メールを見ると本文も宛先も送信先もdiffったが同じものだ。
ただし若干容量が異なった。ヘッダがほんの少しだけおかしいようだ。
・・・見比べてみると2行だけ見たこと無いメールサーバが転送したという情報が書かれていた。
そのヘッダそのものはなにか意味があるものではない。

ここでわかった。

自社のメール送信サーバでお客様Bに送信した。
その時に運用のAさんはBCCに自分のアドレスを入れて送信した。
お客様BのメールアドレスはメーリングリストでAさんもそこに含まれていた。

こっちは自分の送信プログラムが2通送っているのか?という事実にビビっておたおたしていたのに、
…原因は実にくだらなかった。

BCCとかメーリングリストとか、使い方が変なんじゃね?

[教訓]メールが2通届く時に設定ミスでない場合は、BccやMLの設定で転送されていないかチェックスルこと。

--

更に余談だがBccとはクライアントに届く時に余計なヘッダを極力消してしまう。
それが問題をさらにわかりずらくする。Bccって機能じたいどうなの?という議論は昔からあるけど、
そうだな。いらないよな、Bcc。

ネットワーク機器はbpsやppsで性能を計れない。

参考(このブログエントリーの本質については書かれてないけどbpsがあてにならないことは説明されている)
itpro.nikkeibp.co.jp/article/COLUMN/20090617/332116/

標題の通り。ハブもルータもコンピュータに過ぎない。

小さいパケットが複数飛んだりすれば、それだけCPUが動いてメモリに展開され角ポートに振り分けるので、いくらハード全体のbpsやppsがギガビット対応であっても実測値はでません。100BASEのプラネックスのL2ハブの方が1GBのコレガハブより複数ポートを指して利用したら固まらず快適だったことがある。ギガビットという表記に騙されてはいけません。安いギガビットハブより高い100BASEハブの方がみんなでインターネットするなら快適です。

つまり、理論値だけ見ても使えるかどうかわかりません。

特にメモリが小さければさばけず重くなりやがて落ちざるをえなくなるこれが現代型コンピュータの宿命。

だいたいppsなどの総パケット店総数は決まったサイズのパケットを飛ばした最速の理論値に過ぎず、安価なハードはその価格程度の力しかないのは明白です。ちょっと話が逸れますが、この「理論値と実測値は違う」という言い方は、マジックワードというより無意味で曖昧な理解になってしまう原因ではないかとすら、私は思うようになりました。理論値は実測値に伴なわないということは、理論値そのものの出し方に問題があるということだし(bpsは平均値に過ぎないと分かった上で言っています)、とにかく理論値はそもそもあてにならないという理解は変だ。

理論があてにならんと言うのは身も蓋もない。

理論は理論でそれそのものは大変役立つものである。
というスタンスをいわゆる理系/技術者ならとらないとダメでしょう。

理論を実践以下に貶めてはならない。

じゃあなんて言えばいいか?

「ネットワーク機器のマニュアル記載の情報だけでは正確なスループットはわかりかねる」こういう方が理論的でしょう。

RFCではスループットを出すにあたってbpsでもppsでもよいと書かれているらしいですが、
httpでWebサイトを閲覧するとなるとだいたい細かいパケットが沢山飛ぶので64bitで算出した値はでるわけがない。

参考
detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1218091427

本質を理解しないとRFCも読み間違えるような気がします。

コンピュータは奥が深いというか、
本質の受け取り方を間違えると長く迷走する世界だと思う。
他の業界/世界もそうかもしれませんけどね。。

※変に職人技を経験則のせいにしたてあげるのではなく、
 きちんとマニュアルにかかれていない理論が分かれば、
 職人にすぐになれるのだということを私は言いたい。

※自宅にもいつかアライドテレシスの機器でいいから欲しい。

crondでphpのfgetcsv関数が正常に動かない

叩いて動かす分には問題ないが、cronだとCSVの日本語がfgetcsvで動かない。

cronの設定ではよくある話。

パーミッションも問題ないのでおかしいなーと思ったら、
LANGという環境変数に応じてfgetcsv関数は動作がかわるとのこと。

export LANG="ja_JP.UTF-8"
batch.php

※cron設定時に(自分で叩いてデバックしてうまくいくことは確認すると思うが)、
 その時にcronで失敗する時は以下2点を疑うこと。
・環境変数の違いがないか。
・パーミッションに間違いがないか。

【参考】結構事例あり。
www.yuigahama.org/?p=370
tkuchiki.hatenablog.com/entry/2013/04/23/224125
yassu.jp/pukiwiki/index.php?crontab%A4%C7fgetcsv

javaScriptでonChangeでアンダーバー入りの関数が動かない/未定義になる。

タグ上のonChangeに定義済の関数xxxxx_bbbbb_ccccc()というような、
アンダーバーが上記のように2つ入った関数を呼び出すことができなかった。
not defined functionみたいなエラーになってしまう(FireFox33.0.2)。

以下のブログと同じような現象かと思います。
ragranje.blog73.fc2.com/blog-entry-25.html

アンダーバーをなし、または1つの関数にしたり、a_b_c()というような関数にしたら動いた。

意味がよくわからない。アンダーバー無くした関数にして回避したが、注意が必要。

DNSの切り替えは短く見積もっても1カ月

DNSの安全な切り替え方について。

(ドメインに対応するIPアドレスの切り替えで、Webサーバを切り替えた場合の例)

店舗や中小企業のWebページを制作している人は、
ドメインに対応したIPアドレスを変更した場合、
DNSの浸透は数時間せいぜい1、2日で済むと思っているかもしれない。
(というか、私はそう思っていました。)

ところがクリティカルなWebサイトやクリティカルなメールサーバの移行の場合は、
そういったアバウトな感じで行うことはできません。
DNSのゾーン変更でも1~3カ月の長い期間を見て行わないといけません。

なぜでしょう?以下のような理由があげられます。

1.世の中のDNSサーバがTTLを気にしているとは限らない。
  (BINDなどではなく独自実装のプログラムが無いとも限らない)
2.ルータやクライアントサイドのアプリケーションなどのDNSキャッシュは、
  DNSサーバのTTLなぞ気にせず自分のタイミングで廃棄したりもする。

つまり、端的にいえばTTLは相手にキャッシュ保持期間を
マストでコントロールできるものではないのです。

DNSの伝播の仕組みは堅いものではありません。
TTL値が利用されるべきことは相手の性善説に基づくものであって、
それをビジネス上の「正しくアクセスできない」理由にはできないのです。

ですから、DNS切り替えは以下のような手順で行われなくてはいけません。

【DNSサーバの切り替え手順の例】

(1)DNSサーバの変更するゾーンのTTLだけを10分に設定して1,2カ月放置する。
  (世界中のDNSサーバにゾーンの書換えを素早く行ってもらうための情報をばらまく)
(2)ドメインに対するIPアドレスを変更する。
(3)しばらく放置(目安は1~2週間)し、
   Webサーバのログを見てアクセスが無ければ、移行元サーバを停止する。
(4)TTLを常識の範囲(1時間~1日程度?)に戻す。

DNSの安全な切り替えは最低でも1カ月ほどかかります。。

Webサーバでもメールサーバでも切りかえた時は、
1カ月とはいいませんが1週間程度は移行元サーバにアクセスされることがあります。
メールサーバのDNSキャッシュ時間が長いということもあるということなのでしょう。

甘く見ていると痛い目に合うのが「DNSの浸透」です。

慎重に余裕を持って作業をしましょう。

インターネットを支える仕組みとして、
DNS(ドメインネームサーバ)の仕組みが分かるようにしましょう。

[PHP]header関数でリダイレクトしても下部の処理は行われる

liginc.co.jp/programmer/archives/1140

よくよく考えればそりゃそうだ。headerが吐き出されてからクライアントでリダイレクト処理するのだから。

headerの下にある処理はすべて実行される。

これをexitやreturnやkillと同じステートメントと捉えてはいけないのだった。。。

session_start関数を実行していて、ブラウザにきちんとCookieも焼かれている。

…なのに次のページで復元できない。

サーバ側のセッション管理はsession_start関数はtrueを返しているから焼かれているはずだ…が、
指定のディレクトリにはセッション管理用の中間ファイルがない。

別のスクリプトで簡易セッション管理の仕組みをつくれば問題なく動く…非常に時間を無駄にしたが解決。

自分のあほさがいやになる。

なんか前にも嵌ったような嵌っていないような。忘れないようにメモしておこう。

もっとはやく気がつく脳にするにはどうしたらいいのだろう。

既存のサービス(crond)を止めてはならない。

crondはlinuxのディストリビュージョンをダウンロードすればかならず入っているデーモンであるが、そういったデーモンはOSそのものの稼働がうまくいくように動作しているものであるから、停止してはいけないのだそうだ。タイマーにスクリプトを交わすことはunixに限らずwindowsはじめ色々なOSで行うことかと思うが、そうやって1枚スクリプトをかますことはユーザサイドのサービス(OSサイトのサービスとは異なる)を停止させる時に、そのコード内のコメントアウトだけで可能になるという理由があるらしい。レンタルサーバだとユーザ別のcron設定(/var/spool/...)の中でやってしまうのだけれども、Sierなんかではシェルをカマす。カマす理由がよくわかっていなかったがたしかにかました方がいいと改めて思うのでした。不要なデーモンを停止するチューニング方法はあれどcrondに限らず止めない方がいいこともある。(iptableやselinuxがonなのは個人的には邪魔でしかなかったりするが、、、)

ダメなデータフローダイアグラム(DFD)から学ぶ【DFDの原則】

DFDの書き方を間違えて上司に怒られたことが何度もある。

今後は間違えないよう、メモしておくので、書き方が分からない方は参考にして欲しいです。

(DFDは変な先入観を持っていると、正しく書けません)

すでにプログラム/スクリプトをある程度書ける人が、
後からにわかDFDを学習して分かった気になって、
私のように残念なDFDを書いてしまいがちである。

DFDの基本的な書き方は他のブログやIT系記事にゆずるとして、
やりがちがけどやってはいけないことをメインに書いておきたい。

原則1.DFDは1データの流れを表したものである。
(極論だが、以下のようなフローはあり得ない。)

dfd1

途中で別のデータに変わってしまっている。
変わるならば別のDFDとして2ページに分けて書き表わすべきである。

原則2.DFDの終点は必ず1つある。

dfd2

停止しないシステムを模して、動き続ける様子を書きたくなることがある。
だが、そもそもチューリングマシンには停止性がある。
データが計算されて別のデータとして結果が返るというのが基本である。
したがって終点を書かなければならない。

データフローダイアグラムは(フローという言葉が含まれているので明らかだが)フローチャートである。

フロー(滝)の先はdestivation(行き先)が決まっていて、1つの行き先に必ず行きつくということを意味する。

(つまり○○フローな図は必ず終点が1つでそこまでの流れが書かれているということ)ちなみに、あえて循環性を意図して伝えたいならば意図的に循環するDFDを書いてもよい。PDCAサイクルの図のようにループする循環型のシステムの方が、見た目や客受けがいいということもあろうだろう。だが、ジョブ遷移などのステータスが切り替わる、いわゆる状態遷移図と混同してフローチャートを書くことはよくないことを知っておくべきである。

ファッションにおいて、よくないことと知っていて着崩すのと着崩すことが本来の着方だと主張するのは雲泥の隔たりがある。コンピュータ雑誌によく書いてあるような抽象モデルを速読することに慣れている人は特に、注意したい誤りであると言えるだろう。

仕様書として意図を正しく伝えなければいけないという意味では。boolされるdestinationは、wikipediaのページで描かれているようなはっきりしとしたものにしたほうが、私は好きだ(てか、さんざ言ったけど、好みの問題と言えばそれまでだったりするのかも)が、フローは1つのところへ流れつくのが基本(と思う)。

原則3.DFDの始点は必ず1つある。

原則2のおさらい。

すでに、フローの原則は述べた。

源泉(source)は、目的地(destination)まで行く。

そして、源泉は1つ目的地も1つ終点が1つなら始点も1つ
(言葉を変えて、繰り返し説明した。混乱したらすみません。
 始点=スタート=源泉=入力
 終点=ゴール=目的地=出力
 すべて同じ意味だと考えていただいて間違いないです)

dfd3

×入力の無いプロセスCはありえない。
 (原則2のようなプロセスが別プロセスと直接矢印で結ばれるのはありえない)。
×プロセスから2つのデータを出力してはならない。

特定の処理をした結果出力が2つあるならば、論理的に別プロセスに分けること。
(または、individualな結果が1つではないか疑うこと!)

構造化分析を書いたデマルコの書籍を読めば一目瞭然なのだろうが(買ったけどまだ読んでいない)、あるデータがあるデータになって出てくるのが、そもそものプログラム(というかチューリングマシンの原理)である。それをプログラムソース上で正しくコーディングするためにもDFDは重要で必要なダイアグラムである。プログラムの機構に限らず人間界の論理的なシステムを個々に抜き出せばデータフローダイアグラムになるからだ。現実の構造化ということを正しく行うとはどういうことか?という疑問を提示してもいいだろう。

…というわけで、正しいDFDの書き方ではなく、誤ったDFDの書き方が分かれば、それなりに正しいDFDが書けるのではないでしょうか?ということのメモでした。

↓後は、とりあえずデマルコの名著をお勧めしておきます↓