Linuxのxargsには--no-run-if-empty付けとけ

知らなかったというか面倒で放置してた。

cronで定期実行するスクリプトの中に

find PATH CONDITIONS | xargs COMMAND

みたいなのがあったとして、これが時々エラー吐く、みたいなことがあったんですわ。あー xargs の呼び出すコマンド(例えば rm )に入力がないときにエラー出るんかー、変なのーって思いながら、ちょこちょこそれを忘れては引っかかり、をくり返していたんです。

なんでか今日分かりました。BSD の xargs を使った場合はそういうエラー出ないのです。だからすぐ忘れる。

GNU のバカーと思ったりしたのですが、man の恐ろしい量のオプションを読んでいたら

--no-run-if-empty

なんて文字が! なんてこった。というわけで実際のスクリプトの一部はこんな感じにしてみた。

BSD のクセに gnu findutils 使ってるとか cygwin 使ってるやつのことなんか知らない。

[2011-11-09 追記] 最近の BSD xargs には -r というオプションがあって、これが findutils の xargs の -r と同じ動作をするそうです。残念ながら OSX 10.6 の xargs には存在しなかったので普段使いにはできないのですが、サーバ周りでは共通のオプションにできるかも。

zsh の alias というブコメががあるんですけど、cron で zsh 使わないので、それは今回のケースにおいては解法としてニーズに合ってないっす1

  1. そもそも手作業のときは一度 find でリストだけ出すってのが習慣になってるので –no-run-if-empty もまったく必要ないんですよね。 

Web業界と Un*x と Cygwin

駄文 - プログラミングと Shell - IT戦記

モテたいやつは Un*x 使って shell 使って書けと。(嘘)

仰るように基本テキスト処理っつーのは大きいと思います。テキストが「インターフェイス」なのよね。ただ CLI は最初の心理障壁がべらぼうに高いので、GUI のツールにできっこねー技をいくつか披露しておくと(してもらうと)多少はマシかもしんない。別にオレたちゃマゾっ気があって Terminal 開いてるわけじゃない。ジョブズが好きだから Mac 使ってんじゃない。

話がそれた。

cygwin は wget とかでがっつりローカルにミラー作っておくとインストールも更新も早くて楽です。最近はそんなことしなくてもみんな十分回線が速いのかしら。

あとはいつも言ってることのくり返し。

cygwin のメリットは

  • ファイルシステムが Windows と分離しないのに完全な1システムとして動く
    • 同じコマンドを個別にインストールするのと違って楽だし統一感もある
    • cofs 使ったことないんでその辺は分かりまへん
  • shell から Windows のコマンドもそのまま呼べる

この2点だと思う。で、ターミナルは絶対変えた方がよい。これは

から。

/cygdrive/c/

になる問題は

cd /
ln -s /cygdrive/c
ln -s /cygdrive/d

しとくとよいよ。

最近の cygwin は screen もまともに使えるし、結構便利なんじゃないかな。

PostgreSQL 8.1 以降のメンテツールのもと

メンテツールそのものじゃないです。とりあえず上げてみるテスト。こんなのがあると sh スクリプトとかと組み合わせやすいかなーと思う。

DB一覧

最も単純にはこう。

psql -U postgres -t -A -F " " -l | awk '{print $1}'

ただしこれだと template0, template1, postgres が含まれてしまう。

psql -U postgres -t -A -F " " \
-c "select datname from pg_database where not datistemplate;"

にすれば postgres は入っちゃうけど「使える」データベースの一覧が採れる。

テーブル一覧

とりあえずテーブル名だけ

psql -U postgres -c "\d" $DBNAME
psql -U postgres -t -A -F " " -c "\d" $DBNAME | awk '{print $2}'

権限情報付きはこう。

psql -U postgres -c "\dp" $DBNAME
psql -U postgres -t -A -F " " -c "\dp" $DBNAME | awk '{print $2, $4}'

権限付きはいっぺんに取得できない。上と組み合わせてこんな感じ。勘違いして必死こいて awk で sql を組み立てたバージョンも晒しておきます。ほ、ほら、sql を書き換えればいろんな情報が採れるよ!とかほざいておく。

psql -U postgres -c "select relname,relacl from pg_class where relname \
in (`psql -U postgres -t -A -F ' ' -c '\d' $DBNAME | awk '{print $2}' |\
awk -F '\n' -v RS='' -v ORS='' 'BEGIN {print \"\047\"}\
{gsub(/\n/,\"\047,\047\"); print}\
END {print \"\047\"}'`)" $DBNAME

なんでこんなまどろっこしいことやってるかっていうと pg_class の結果からシステムが用意したテーブルかどうかを判断する基準が分からなかったから。

スクリプトの長さはともかく、SQL を生読みするよりは多少権限付与の状態が見やすい……んじゃないかなぁ。

{ }

の中を , で split するとかは好きずきってことで。

select relname,relacl from pg_class where relname in

の部分を

select relname,relfilenode,relpages,relacl from pg_class where relname in

ってやっとくとディスクスペースの確認もしやすくなる1。インデックスとか入ってないけどそこら辺は適当で、ひとつ。

role一覧

※ たぶん 8.1 以降専用なのはここだけだと思う。

まずはまんま。

psql -U postgres -c "\du"

ユーザー名とグループのみに絞ってテキストデータだけにするとこんな感じ。

psql -U postgres -t -A -F '|' -c '\du' | awk -F \| '{print $1, $6}'
  1. この page の単位ってよく知らないけど、node が分かれば ls -lh? とかで容量の確認はできる。ま、フツーそんな細かいレベルの情報は必要にならないというか、そんなの気にしちゃダメっぽい。もっとざっくり効率がいいか悪いかとかディスクに収まるかどうかだけ見ろと言いたいらしいぞ。知らんけど。 

text/javascript って obsolete なんだ

RFC4329 - Scripting Media Types

application/javascript
application/ecmascript

にしろってか。ブラウザの対応とかどうなってんだろ。

まぁ JSON が application/json になったんだから、その時点で気づけってんだよな。

なんかネタかぶりしてるけど、ぼかぁたまたま IANA Media Types を見に行っただけですよ。

というかチェックしてるはずの神崎さんのメモをなんとなくスルーしてる段階でアンテナ感度が鈍いっつー話なんだよなぁ。あ、今 Camino 1.0.3 でチェック用のボタンを押してみたら全部動いた。てことはこの方法でちょっとでも古いブラウザを根こそぎ排除できるかも(笑)

と思ったら IE7 はダメらしい。おいこら。

※ まったく本題じゃないんだけど、リンク先のページを改めて見て気がついた。Camino でも Gecko 風のボタンが表示されている。これは Safari 1.3 でも同じ。input type="button" の場合はちゃんと Aqua なボタンになるのに、button 要素の場合は昔ながらのボタンぽい表示になる。Opera 9.0.2 ではどちらも Aqua 風になる。

XMLHttpRequest を使ったスクリプトのロードは意外と面倒

  1. XMLHttpRequest を使ったスクリプトのロードを自分で書いてみた
  2. JSAN を読んでみた
  3. JSAN よくできてる

という話。

  • XMLHttpRequest で取得できるのは「データ」である
  • 「データ」を「スクリプト」にするためには eval() する必要がある
  • eval() した結果できるコードは eval() された場所のスコープに制限される

つまり、例えば

// スクリプトをロードするつもりの関数
function load( url ) {
  // XMLHttpRequest で同期通信でコードを取得する処理
  // 取得に成功したコードを eval()
}

load( hogege );

// ここでエラー
function_defined_external();

ということ。function_defined_external() という関数が load() で読み込んだスクリプトの中で定義されていても、それは load() の中で eval() したら load() の中でしかコードとして存在できないわけです。

これはこうなっていれば ok です。

function load( url ) {
  ..
  // 読み込んだデータをそのまま返す
  return xhr.responseText;
}
var script = load( url );
if ( script ) {
  eval( script );
}

// これは実行可能
function_defined_external();
  // (ちゃんとライブラリをロードできていれば)
  • 読み込む関数は読み込みしかしない
  • 返って来たテキストデータを「自分の意思で」「動かしたいスコープで」 eval() する

という二段階の操作になっちゃうけども、こうすれば問題なく使える。二段階はどうしてもイヤだっていうんでなければこの方法がいちばん手軽だと思う。1

しかし JSAN はこういうかっこ悪いことはしていない。use(), require(), export() が自在に活躍してくれる。これは、

  • オブジェクトをちゃんと活用しているから
  • 命名規則を設けているから

まぁ簡単に言えば JSAN.use() の中で eval() してできあがったオブジェクトのプロパティを Global なオブジェクトのプロパティにコピーすれば使えますよということ。これは prototype.js とか最近のモダンなライブラリがみんなやってる「プロパティコピペしまくりの術」の応用なわけですな。うまいこと考えたなぁ。

ただ、逆に言うと

ちゃんと JavaScript でオブジェクトを扱える人でないと JSAN を利用してロードするライブラリを書けない

ということです。

つかまず一発勝負関数とかあるわけですよ、やっぱり。すべてのコードが名前空間やオブジェクトを意識して作られた整然としたコードにはなっていないわけですし、最近の便利なフレームワークも別に JSAN の枠組みには則っていないわけです。

そういうときは上の二段階方式が扱いやすくていいな、と思っています。先の記事で書いた require() は bookmarklet など他ドメインのスクリプトをロードしたいときに、XMLHttpRequest を利用した load() は同一ドメインの無作法なライブラリ(笑)や、そのまま script 要素に書いて読み込むと MacIE などの古いブラウザでコンパイルエラーが起きてしまうライブラリ2のロードに利用していったらいいかなと思っています。

  1. with を使って window オブジェクトのスコープで eval() するって方法もあるけど。 

  2. prototype.js も JSAN もみーーーーーんなそうじゃ! 

OSX で system() が返す status がちょっと変

system() でプログラムの外部のコマンドを呼び出すとします。このとき、呼び出しの成否をステータスコードで取得できる…のですが、

 成功失敗
Linux1127
OSX 10.3.9(Darwin 7.9.0)0127
OSX 10.4.3(Darwin 8.3.0)0127
FreeBSD1127

になってて、1 を期待してたら何が起きてるのか分からずに困った。

Manpage of SYSTEM を見ると 127 の方で判断すりゃいいみたいだけど、そういうもんなのかな。ちょっとびっくり。

About

例によって個人のなんちゃらです