GSSAPI 

SSHでGSSAPIAuthenticationとかGSSAPIに関する設定項目がある。今まで特に気にしていなかったのだけれど、これは使えば結構便利らしい。
暗号やプロトコルのネゴシエーションをやってくれるのがGSS機構で、そのAPIがGSSAPI。SSH等のプログラムはGSSライブラリをダイナミックリンクして使う。
SSHなどのプログラムは、暗号やプロトコルのネゴシエーションをGSS機構に任せて、両ピアがサポートする最良の暗号やプロトコルを決めてもらうことになる。
うまく使うとKerberos認証とかも使えるようになるらしい。

ただ、CentOS7にSSH接続しに行く時、GSSのネゴシエーションで待たされるのがちょっと嫌かな。

CentOS7って大幅に変わってるね。 

CentOSって大幅に変わってるね。

NTPもchronyに変わっているし、/etc/sysconfig/i18nとか/etc/clockとかもなくなって、よりにもよってコマンド(datetimectlだっけ?)で設定とか。

CentOS7で導入された管理コマンドって(firewall-cmdとかsystemctlとか)引数が長ったらしくって、複数形だったり単数形だったり、オプションもものすごく多かったりで、とても覚えづらい。

とはいえ、長期間メンテナンスしてくれるディストリビューションで、仕事に普通に使えるようなメジャーなものを他に知らないので、とりあえずはCentOS/RHELを使うしかないのだけれど。

気分的にはなんだか嫌。

net-toolsおじさんなのでブチ切れた話 

最近、緊急の障害対応でMACアドレスを調べる必要が発生した。

$ arp -an
net-tools コマンドはもう非推奨ですよ?おじさんなんじゃないですか? Use `ip n`
$



ブチ切れそうになったが、「非推奨になったネットワークコマンド養成ギプス」を導入しようとaliasを自分で設定したのでなんとか我慢した。
続いてIPアドレスを再度確認しようとした。

$ ifconfig -a
net-tools コマンドはもう非推奨ですよ?おじさんなんじゃないですか? Use `ip a`, `ip link`, `ip -s link`
$


癇癪を起こしそうになった。
俺の小宇宙は爆発寸前だぜ!
早くnet-tools小父さんを卒業しなければ死ぬ。

journaldがキモい(と感じられる) 

CentOS7でjournaldが導入されている。

日経BPのサイトでjournaldの使い方を軽く紹介されていたので読んだのだけれど、journalctlでログを参照しないといけないとか、その引数がかなりキモいとか、嫌な方向に変わっていくと思った。

[r]syslogの取りこぼしについて 

時々、ブログで[r]syslogは取りこぼして使いものにならない、的なことを言っている人がいます。本当にそうなんでしょうか。
[r]syslogdのやることなんてとってもシンプルで簡単な事じゃないですか、UDPパケットが届いたら事前に決められていたファイルへ追記する、メインはこれだけじゃないですか。
これで取りこぼしが出るような(r)syslogが、OS標準でついてくるのが当たり前っていうのはおかしいと思うんだよね。だから、取りこぼすにはなにか理由があって、それは使い方/設定内容のせいではないかなと想像していたわけ。

自分のところであった症状
そんなことを考えていたある日、10秒に1件程度しか出力されていないログが、どうやらrsyslogサーバで捨てられているらしいことが分かった。2台の機械から同じようなテンポでログが出力されているはずなのに、どちらか片方からのログしか記録されないんだよね。本当はもっと頻繁にログ出力されているのに違いない。

名前逆引きの失敗が原因なんじゃないの
困るんで調べてみたんだけれども、rsyslogdが標準では受信したsyslogパケットの送信元IPアドレスを逆引きして名前解決しているらしい。syslogの送信元機器IPアドレスは/etc/hostsにもDNSにも登録されていなかったので名前解決にタイムアウト、失敗してようやくログがファイルへ出力される。失敗が確定するまでに時間がかかり、他のパケットが捨てられている、ということらしい。

ログを送ってくる機械をrsyslogdの動作している機械の/etc/hostsへ書いてあげた所、トラブルは直った。原因はやはり名前解決の失敗だったらしい。


で、rsyslogを使うときに機器の名前登録なんかそもそもしたくない場合がある。そういう場合にはオプション-xを付けてやればよい。これで受信したsyslogパケットの送信元IPアドレスを逆引きしなくなる。CentOS6で設定を行う場合には

[/etc/sysconfig/rsyslog]

SYSLOGD_OPTIONS="-c 5"
 ↓
SYSLOGD_OPTIONS="-c 5 -x"



と変更して、(オプション"-c 5"はオプションの先頭にないといけないので注意)

service rsyslog restart



とする。多分 service rsyslog reload ではうまく反映されない。変更点がコマンドライン引数だから。
もちろん、ログに残されるログ送信元はホスト名ではなくてIPアドレスになってしまうのは仕様です。ホスト名で記録したければDNS登録なり、/etc/hosts登録なりして下さい。ただ、syslogサーバにsyslogを投げてくるマシン全部もれなく名前登録してやらないといけないんじゃないかなぁ。

ということをしないままログを取りこぼす、とか言っているんじゃないだろうかなぁと推測してみたり。
本当はどこまで問題なくログを処理できるのか、リモートからabみたいなのを使ってベンチマークすべきなんだろうけども、どうやるのが正しいんだろう? perlでsyslogを直接投げるスクリプトを作成、ループで回すんだけども、ループごとにミリ秒単位でウェイトを入れてみる、とかやればいいのかな?

ファイル書き出しをバッファしていないじゃないの
それでもsyslogが思いとか、ロスるとか言っている場合には、ファイルへの書き出しが同期書き出しになっているんじゃないのか。

daemon.info /var/log/daemon.log


とかって設定になっていたりするのを、ファイルパスの先頭に'-'をつけることでsyslogdがファイルへ書き出す際にバッファしてディスクへの書き出し負荷が小さくなるようにしてくれる。

daemon.info -/var/log/daemon.log


それでもうまく行かない場合であっても、[r]syslogdの実装を疑うより、何か他の原因を探した方が短時間で幸せになれると思うけどな。

ファイルのタイムスタンプのctimeは簡単には変更できない 

少なくともLinuxのファイルシステム(ext3とか4とか)ではctime(ファイルの作成、属性変更された日時)の設定ができないとのこと。これって結構意外。
touchコマンドではmtimeとatimeは任意に設定できるけど、ctimeは設定できない。(HP-UXではtouchコマンドで設定できる模様)

perlの関数utime()でも同様にmtimeとatimeは設定可能だけれど、ctimeは設定できない。
株式会社参謀本部の社長ブログによれば、コマンドdebugfsで無理やり書き換えることが可能とのこと。
だけどまぁ、ここまでやってファイルシステムを直接書き換えるのはいかがなものかと思ったり。しくじったらfsckやらないといけないじゃない。

デジタルフォレンジックの世界ではファイルのタイムスタンプとかも調べるんだろうね。その場合、ctimeは簡単にはいじれないので役に立つのでしょう。

findを極める 

findは沢山のオプションがあり、ちょっとやそっとじゃ全体を覚えて日頃活用しきることが難しいコマンドの一つではないか。とかって思ったので少しずつ調べてみることにした。

-print0
-printと同様にパス付きのファイル名を出力して真を返すが、ファイル名の後ろに\0(ヌル文字)をつける。こうすることでファイル名に改行などを含む特殊なファイルを処理することができる。xargsのオプション-0と対応している。

man findによれば、ファイル名には'\0'と'/'以外のどんな文字も使用できることになっているので、何も考えずに-printによる出力を改行区切りで処理すると意図したことを実現できない場合があるわけだね。(つまり、出力したファイルのファイル名に改行が含ま れていた場合、ファイル名の途中までを一つ目のファイル名として扱い、改行の後を2つ目のファイル名として扱うことになってしまうわけだ)

さて、改行を改行文字(LF, CR)以外で示すファイルフォーマットは(最近は)それほど見かけなくなってきているので、自分がよく使うperlで'\0'を改行文字として扱うための手順がよくわからない。多分、改行文字を示す特殊変数に'\0'を代入してやって

while(<>){}

を回す、とかすることになるのではないだろうか。

-maxdepth DEPTH
findで探索するディレクトリのトップから何階層下までを探索対象とするかを指定。これだけみると簡単なのだけれど、こんなシンプルなmaxdepthにも落とし穴がある。以下のように実行するのは実用上誤りなのね。

find /dir -type f -name filename -maxdepth 5


/dir配下にある、ファイル名が"filename"であるファイルを-printすることを意図しているのだけれども、多分期待したものよりもずっと実行時間が長く掛かるはず。
findは検索条件チェックを、コマンドラインの先頭から順に行うようになっているらしいので、コマンドラインでの指定順によって実際に行う動作が変わってくることがあるのね。今回の例だと、/dirからディレクトリエントリを一つずつ拾っていき、各ディレクトリエントリに条件"-type f"と"-name filename"のチェックをした後に"-maxdepth 5"のチェックを行うことになる。多分、/dir配下の全ディレクトリに対して探索を行うんじゃないだろうか。
正しくは以下のようにする。

find /dir -maxdepth 5 -type f -name filename


これで5階層以上深いディレクトリであれば何も考えずに探索をやめるため、探索対象がぐっと減ることになる。
-exec
-execは結構必須でいつも使うオプションなのだけれど、いつも気にしないところでちょいと役に立つ知識が埋まっていた。
配下に沢山のファイルが存在する場所を対象として、

find / -exec ls -ld {} \; | head


とかって実行すると、多数のエラーメッセージが出力されて-execで指定したコマンドlsがシグナル13で死んだと報告される。
シグナル13は"SIGPIPE"で、読み手の無いパイプへの書き出しをしようとした時に発生する。実際には、lsが起動されて書き出しをしようとした時にはそれを読むべきコマンドheadが終了していたということ。(もちろんheadで出力される最初の数回のコマンド実行は正常に完了する)
多分、コマンドfindは高速化のために色々と工夫をしていて、パイプの後ろのheadコマンドが生きているか死んでいるかを確認せずにファイルを見つける度にlsを起動、出力をheadへのパイプに接続していくんだろう。この結果、大量のエラーメッセージが出力されるというわけだ。たぶん、find自体が標準出力へ出力する必要が出るまでは、findが読み手のないパイプへ書きだそうとして終了することはないのだろう。
このエラーメッセージはかなり鬱陶しいし、実用上も必要な画面出力を流してしまうため出力されるのを避けたい。いろいろ調べて見つけた方法は次のように、オプション-execのターミネータとして\;ではなく、+を使用する方法。

find / -exec ls -ld {} + | head


-execのターミネータとして\;の代わりに+を使用することで、見つけたファイル一つごとにlsが実行されるのではなく、1回のlsコマンド実行で複数のファイルをまとめて指定して実行される。しかも引数文字列が長すぎる場合には、コマンドラインの長さ制限の許す範囲で切り、分割して実行してくれる。
このように実行すると何故かエラーメッセージの出力が1回だけに抑えられ、鬱陶しさがかなり抑止される。なぜこうなるのかはよく分かっていないのだけれども、どうしてなんだろう?

-mtimeと未来のタイムスタンプ
-mtimeなどでファイルのタイムスタンプでフィルタする場合に、検索対象ディレクトリに未来のファイルが存在すると何が起きるのか。以下のようにして"N日より新しいファイルを処理する"と指定すると、未来のファイルも含めて処理される(当たり前)。

find . -mtime -1 -exec ls -l {} +


このコマンドを以下のように変えて、"昨日更新されたファイルを処理する"ということを意図して1日1回実行すると、未来のファイルが何回も処理されることになり都合が悪い。

find . -daytime -mtime -2 -exec ls -l {} +



1ヶ月先のタイムスタンプを持つファイルAは、今日も明日もその次も毎日処理されることになる。昨日更新されたファイルでもないのに。明日以降のタイムスタンプを持つファイルを除外するためには以下のようにすればよい。

find . -daytime -mtime -2 -mtime +0 -exec ls -l {} +


findの引数は登場順にテストされるので、まず "-mtime -2" で昨日以降に更新されたファイルであるか確認し、そうでなければ次のファイルへ進む。
次に "-mtime +0" で明日より前に更新されたファイルであるか確認し、そうであれば-execを処理するということになる。

それでふと疑問に思ったのだけれど、今日も除外したい場合にはどのようにオプション指定すればいいのだろう?

find . -daytime -mtime -2 -mtime +1 -exec


ムムムッ!?

あれ?、なんだこれ、

-mtime -+N とか、
-mtime +-N とか指定できる。

更に出力される内容が異なる。どんな指定になっているんだ? ワカラン

あ、ちなみに未来のタイムスタンプを持つファイルを作ることは結構簡単にできる。(mtimeやatimeなら) こんな感じ。

$ touch -t 4512312359 /tmp/test
$ ls -alF --time-style=+"%Y/%m/%d %H:%M:%S" /tmp/test
-rw-r--r-- 1 user users 0 2045/12/31 23:59:00 /tmp/test
$


調子に乗って2099年を指定したつもりになったらtouchコマンドでは駄目だった。

$ touch -t 9912312359 /tmp/test
$ ls -alF --time-style=+"%Y/%m/%d %H:%M:%S" /tmp/test
-rw-r--r-- 1 user users 0 1999/12/31 23:59:00 /tmp/test
$


そしてファイルのタイムスタンプのctimeは簡単には変更できない

ls -l の出力の'.'(ドット)と'+'(プラス)の意味 

Linuxでls -lを取ると、パーミッション欄の末尾に'.'(ドット)や'+'(プラス)がつく場合がある。

$ ls -l
合計 4
-rw-rwxr--+ 1 user users 55 1月 23 14:55 2014 cc.txt
$


これの意味は以下の通り。

. SELinuxセキュリティコンテキストが設定されている
+ setfacl/getfaclで扱われるACLが設定されている
  (SELinuxのセキュリティコンテキストも設定されている場合も'+'になる)


とはいえ、SELinuxのセキュリティコンテキストってどうやって設定/確認するのか知らないので、なんともかんともなんだけど。

USB HDDにrsyncでファイルをコピーしたらロードアベレージが上がって処理落ちした話 

rsyncでSATA HDDからUSB HDDへファイルコピーしたらロードアベレージが4程度まで上がり、SNMPポーリングで応答を取りこぼすということがあった。SATA HDD→SATA HDDのrsyncではロードアベレージなんか大して上がらないのに、コピー先がUSB HDDだとこういう違いがあった。
ロードアベレージが上がっているときはtopでusb-storageというプロセスがある程度CPUを使っていたものの、CPUはそんなに忙しくしていなかった記憶が。あと、このマシン、SambaでファイルサーバをやっていてwinbinddでADからユーザ名やグループ情報を取得する必要があるので、rsyncでガンガンファイルコピーするとユーザ/グループ情報の問い合わせが沢山発生する。
このSambaが関係しているのかな、それともUSB単体で問題なのかな、と思い、調べてみた。

旅モバによれば、低速なUSBインタフェース越しのHDDアクセスによって、読み出されたコピー元ファイルデータがディスクキャッシュに大量に蓄積して、結果として物理メモリ不足を起こしてサーバ全体の負荷が上昇したということの模様。ブログにはUUIDの扱い方法についても書かれていて便利。
「搭載メモリはそんなに小さくないぞ?」と思うものの、ディスク容量に比較すれば確かに小さい、とても小さい。Linuxは昔からアグレッシブにディスクキャッシュするOSだったはずなので、上記ブログに書いてあることは正しいように思えるなぁ。

しかし、mountオプションを変更してもう一度試す勇気はないなぁ。ああそうだ、別マシンを構築してそちらで試してみるというのがいいのかも。より小さいメモリのマシンで試してみれば、容易に再現するはずだよね。ああ、ただwinbindまで用意するのは面倒臭い…

物理マシン上のLinuxをVMware vSphere ESXi 5.5へコンバート 

物理マシン上のLinuxをVMware vSphere ESXi 5.5へコンバートしたいがうまく行っていない話。

物理マシン上のWindowsをVMware vSphere ESXi 5.5へコンバートする場合、WindowsにVMware vCenter Converterをインストールしてクライアントにて自分自身をESXiへコンバートする事ができるのでやり方は分かるのだけれど、コンバート対象が物理マシン上のLinuxとなるとよくわからない。ConverterはWindowsプログラムであるため、Linux上で実行できないので。

試しにちょっとやってみた。まずマシンとして(A)ESXi(VMホスト)、(B)Linux(変換対象の物理マシン)、(C)Windows(VMware vCenter Converter実行機)の3台を用意する。
(1)(B)でSSHを設定
  rootがパスワード認証で(C)からログインできるように設定する
  コンバートはSSH経由で行われるらしい
(2)(C)上でConverterを起動
(3)「Convert machine」→「Select source type」にて"Powerd-on machine"を選択→"A remote machine"を選択
(4)「IP address or name」にて(B)のIPアドレス、「User name」で"root"、「Password」でrootパスワード、「OS Familly」で"Linux"として「Next」
 ここで何故か"この操作の実行権限が拒否されました。"とメッセージが出力されて先へ進めなくなる。
 ↓
 Converter自体を管理者権限で実行する必要があった(なぜ?)
(5)コンバート完了後ゲストをブートするとkernel Panicで死ぬ。

原因は何? なんでkernel panicになっちゃうんだろう?