スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

でぶぬる

昨日も書きましたが、振り返ってみると、このブログではいつも役に立たないことばかり書いているような気がするので、たまには役に立つ(?)ことを書いてみたいと思います。

ただし、お酒や断酒に関係した内容ではなくて、コンピュータに関する話です。このブログには、当初から、「その他」以外に3つのカテゴリを作っていて、「断酒」と「音楽」と「コンピュータ」の話を書こうと思ってブログを始めたんですが、「コンピュータ」の話題は書いたことがなかったので、一度、書いてみたかったんです。(というか、毎回、お酒や断酒のことばかりで、もうネタがないんです(泣)。)

なお、僕は、いわゆるパソコンや今流行りのスマートフォン等については、普通の人と比べても詳しくない方の部類に入るくらいなので、システムエンジニアの端くれとして、仕事をしていた時に使っていたコンピュータシステム寄りの話になります。

記事のタイトルの「でぶぬる」というのは、UNIXファイルシステムの「/dev/null」のことです。0バイトの空のスペシャルファイルで、一見、使い道がないようですが、標準出力や標準エラー出力に出力されたメッセージを抑制したい場合などによく使われます。

あとは、空のファイルを作成する場合などに使用されることもありますが、空のファイルを作成するだけだったら他にもいろいろな方法があって、人によって好みがあるみたいです。(こういう、UNIX的な思想や哲学が好きです。)

例1)空のファイルの作成方法いろいろ(太字はコマンド)

sh-3.2$ cat /dev/null > newfile1
sh-3.2$ touch newfile2
sh-3.2$ echo -n > newfile3

sh-3.2$ ls -s <- ファイル名とファイルサイズの表示
合計 0
0 newfile1 0 newfile2 0 newfile3


echoコマンドで空のファイルを作成する場合は、-nオプションをつけないと、改行コードが1バイト含まれてしまうので注意が必要です。また、touchコマンドは、本来はファイルのタイムスタンプを更新するためのコマンドなので、この用途では新規ファイルの作成の場面でしか利用できません。

それで、「/dev/null」の一般的な利用の仕方は、標準出力や標準エラー出力の出力が邪魔な場合に、以下のようにコマンドを実行して、「/dev/null」にリダイレクトします。その前に。。。

「いいか、絶対、rootで実行するなよ!君と僕との約束だからな!」(すいません、このネタを一度やってみたかったんです。)

例2)標準エラー出力のリダイレクト

sh-3.2$ cat /etc/shadow <- コマンドを実行
cat: /etc/shadow: 許可がありません <- 読み込み権限がないのでエラーが出力される
sh-3.2$ cat /etc/shadow 2> /dev/null <- 標準エラー出力を/dev/nullにリダイレクト
sh-3.2$ <- /dev/nullにリダイレクトしたので、エラーは出力されずにプロンプトが戻って終了

例2)を試してみて、最初のコマンド実行後、「許可がありません」というエラーメッセージが出力されなかったという方は、僕との約束を破った証拠です。さっさと、rootから抜けて、もう一度やり直してください。

で、ここまでは当然、少しでもUNIXをかじったことがある人にとっては何の役にも立たない話なんですが、シェルスクリプト中などで、例えば次のような処理を実現したい場合があったとします。

例3)シェルスクリプトで実現したい処理

sh-3.2$ cat /etc/shadow 2> /dev/null | wc -l
0
sh-3.2$ if [ $? -ne 0 ] ; then echo 'Error' ; fi
sh-3.2$
 <- 何も出力されずプロンプトが戻って終了(本当はここに'Error'を表示させたい)

えーと、何が言いたいかというと、1行目のパイプでつなげたコマンドの実行結果に何らかのエラーが生じた時に、3行目の戻り値の判定によって、画面上にechoコマンド等で'Error'と出力させたい場面があったとします。でも、通常、コマンドの戻り値を取得するのに使われる「$?」では、パイプの後のwcコマンドの実行結果によって判定されてしまうため、パイプの前のcatコマンドで発生したはずのエラーは、/dev/nullに標準エラー出力をリダイレクトしている状況では検知することができませんよね。

僕は、以前、会社を辞める前に最後に参加したプロジェクトで、この問題に直面して本当に悩みました。(もちろん、実際のスクリプトに実装しようとしていた処理はもっと複雑です。念のため)。「そんなのUNIX使いなら自分でコマンド作ればいいじゃん。」って言う人もいるかもしれませんが、そんな実力はなかったんです(きっぱり)。

それで、ネットで調べまくったところ、bashにはPIPESTATUSという変数が用意されていることを発見しました。

例4)PIPESTATUS変数の使用例

sh-3.2$ cat /etc/shadow 2> /dev/null | wc -l
0 
<- ここまでは例3)と同じ
sh-3.2$ if [ ${PIPESTATUS[0]} -ne 0 ] ; then echo 'Error' ; fi
Error <- PIPESTATUS変数の戻り値判定による出力

期待通りに「Error」と出力されました、感動モノです。ただし、このPIPESTATUS変数は、残念ながらbash限定の機能です。もし、bashが利用できない環境だったら、僕も参加していたプロジェクトを抜けられず、会社も辞めることができなかったかもしれません。(今となっては、そっちの方が良かったような気もしますが。)

今回は、このPIPESTATUS変数の紹介だけで、十分役に立つんじゃないかと思っていたんですが、記事を書くためにもう一度ネットで調べてみたところ、僕がこの変数の存在を知ってから4年近く経っているので、すでに知っている方も多いようです(もはや常識?)。その中で、この処理をbashを使わずに実現する方法を解説している方を発見したんです。(この人、すごい!ていうか、真のUNIX使いとしては当然?)

UNIXの部屋 コマンド検索: リダイレクト
http://x68000.q-e-d.net/~68user/unix/pickup?%A5%EA%A5%C0%A5%A4%A5%EC%A5%AF%A5%C8

リンク先のページの最後の宿題の部分が該当箇所ですが、今回使用したコマンドに置き換えて、実際に実行してみました。

例5)bash(PIPESTATUS変数)を使わない方法

sh-3.2$ exec 3>&1 ; status=$({ { cat /etc/shadow 2> /dev/null 4>&- ; echo $? 1>&4 3>&- 4>&-;} | wc -l 1>&3 3>&- 4>&- ;} 4>&1)
0
sh-3.2$ if [ $status -ne 0 ] ; then echo 'Error' ; fi

Error <- PIPESTATUS変数を使わずに$statusの戻り値判定で出力

素敵過ぎます。こんな方法、当時は思いつきもしませんでした。えっ、「2つ目のコマンドがエラーになった場合は?」って。そんなの「$?」で戻り値取れよ、うるせえな。「じゃあ、パイプでコマンドを3つ以上つなげた場合は?」って。そんな難しいことオレに聞くなよ、てかbash使っとけ。正直、どうしてこれが実現できるのかうまく説明できるほどには、よく分かってないんです。(しくしく。)

ところで、最近知ったんですが、UNIX系システムエンジニアの間では、「でぶぬる(/dev/null)」が大酒飲みという意味で使われることがあるんだそうです。ということは、キックオフの飲み会とかで、

「お前は本当にでぶぬるだな。」

なんて使うんですかね。いや、聞いたことがないんですけど。現場を離れてもう大分経つので、もしかしたら今は使うのかもしれません。うーん、このままじゃ社会復帰は遠いな。

また、くだらないことを書いてしまった。○| ̄|_

追伸:今回の記事で紹介したPIPESTATUS変数を使用しない方法は、他にも別のやり方が解説されているのは見つけたんですが、記述されている内容が正しいかどうか検証する余裕がなかったので紹介していません。別のやり方をご存じの方や記事に誤りを見つけた方はご教授下さい。<(_ _)>

ブログランキングに参加しています。よろしくおねがいします。
   ↓↓↓
にほんブログ村 酒ブログ 禁酒・断酒へ にほんブログ村 メンタルヘルスブログ アルコール依存症へ  

UNIXという考え方―その設計思想と哲学 Mike Gancarz (著), 芳尾 桂 (翻訳) 新品 ¥1,680
スポンサーサイト
PR
つぶやき
買うもの
トブラデックス点眼液
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。