Skip to content

Latest commit

 

History

History
3290 lines (2099 loc) · 134 KB

all.rst

File metadata and controls

3290 lines (2099 loc) · 134 KB

イントロダクション

ここから、Coreutilsのマニュアルに入ります。Coreutilsのマニュアルの第1章は、「Introduction」から始まっています。少し読んでみましょう。

Coreutilsのマニュアルは、絶賛製作中です!初心者向けに基本的な概念は説明してないよ!興味があれば改善していってね。 あと、バグを見つけたら bug-coreutils@gnu.org に送ってね。そのとき、再現環境も一緒に送ってね! [1] だそうです。

[1]あとは先人たちの名前が書かれています

よくあるオプション

例えば、 ls -l-l がオプションです。ちなみに、 sort -r password -t : と実行すると、 sort -r -t : password として実行したように動作します。コマンドによっては、ものすごい長いオプション名がありますが、省略することができます。 rmdir --ignore-fail-on-non-empty の場合であれば、 rmdir --ignore-fail とか rmdir --i で実行できます。ls --h のときは、複数のオプションにマッチするので「分からへん」 [2] と言われたり、「どれやねん」 [3] と言われたりします。

[2](coreutils 8.4) ls: option '--h' is ambiguous
[3](coreutils 8.25) ls: option '--h' is ambiguous; possibilities: '--human-readable' '--help' '--hide' '--hide-control-chars'

以下、Coreutilsでの共通のオプションです。

.. index:: help

--help

たとえば ls のコマンドのオプションを調べたいとき

$ ls --help

簡易ヘルプはこのオプションをつかえば問題☆解決。え?問題が解決しない?そんなときはこのようなコマンドを打ってください。

$ man ls
$ info coreutils ls

infoコマンドを打った後は、Emacsのキーバインドなのでそこさえ気をつければinfoコマンドは良いコマンドだと思いますよ(白目

.. index:: version

--version

バージョンを表示します。

.. index:: --

--

このオプションを打った後は、オプションが無効になります。 たとえば、こんなコマンドを打ったとき

$ ls -l -- -l

-lというファイルあるいはディレクトリをls -lで表示します。

$ mkdir -- -l

とやると、 -l というディレクトリが出来ます [4] 。touchでも同様。

[4]そんな名前のディレクトリとかファイル作るなよ!あとで面倒だぞ!!改行コードだけのファイル名も作れるぞ!作るなよ!!(フラグ
.. index:: -

-

ただのハイフンです。

オプションじゃないよ! [5] 。オプションに見えるだけだよ?ホントだよ?すたんだーどいんぷっとを待つ記号だよ! 受け取った結果はコマンドがよろしく処理するよ!たとえばこんな感じだよ!あとで出てくるから覚えておいてね!

[5]と、マニュアルに書いてあります
$ sort -
b # 打つべし
a # 打つべし
c # 打つべし
Ctrl-d # ctrl押しながらdって打つと下記のように表示されるよ!
a
b
c

その他、Coreutilsの共通したこと

2章は、2.1章から2.14章まであります。かいつまんで、書いてあることを説明します。

返り値(Exit Status)
コマンドを実行したときに数値が返ります。コマンドを実行したあとにすぐ echo $? をやると出てくる数値です。0が通常にコマンドが終わったことを示し、1は異常があったことを示します。0,1以外の数値を返すコマンドもあります。chroot, env, expr, nice, nohup, numfmt, printenv, sort, stdbuf, test, timeout,tty です。
バックアップオプション
-b オプションです。 cp , install , ln , mv にあります。ファイル操作するときに元のファイルをどのようにバックアップするか指定します。サフィックスをつけるなら -S オプションです。詳細は各コマンドを参照してください。
ブロックサイズ
blocksのサイズを設定することができます。キロバイト(kB)やキビバイト(K,k,KiB)とかのあれです。df, du, ls あたりで使います。
ユーザ名とIDの曖昧さの除去
ユーザ名が数字の場合どうなってしまうんでしょうか。そのあたりは、chownあたりのコマンドに詳細を書きました。
ランダムデータのソース
sort -R コマンドで --random-source=file を与えるとfileを元にランダムにソートします。詳細は shufコマンドを参照してください。

スペシャルビルトインコマンド

nice . foo.sh
nice :
nice exec pwd

といったコマンドは意図した結果にはなりません。bashにもスペシャルビルトインコマンドがあって、 nice suspend とかできません。 ビルトインコマンドには、下記があります。

. : break continue eval exec exit export readonly return set shift
times trap unset

他には、浮動小数や、シグナル一覧や、ディレクトリの指定の方法や、/ の取り扱い方、symlinkのたどり方などがあります。

この素晴らしいファイルに出力を!

すごい高貴なファイルの気配がありますね。え?なさそう?そう言われるとそんな気もする [6]

[6]原題は、Output of entire files。元ネタは、この素晴らしい世界に祝福を!
.. index:: cat

cat

Linuxの基礎として間違いなく出てくるコマンドではないでしょうか。 ファイルを引数にとると、そのファイルの中身を表示するコマンドです [8] 。 fileというファイルの中身を出力するときにはこうします [7]

[7]でかいファイルとかバイナリとか食わせるなよーどうなっても知らんぞ!!持ち主の分からないファイルは ls -lh とか file コマンドで確認するんだぞ!!
[8]説明が足りないと気づいた方は正しいです。coreutilsのマニュアルの通りの説明は後ほど
$ cat file

次に、マニュアルにあるオプションの読み方を説明します。説明しますよ!! [9] マニュアルには

cat [option] [file]...

とあります [10]

[9]重要なことなので2回書きました
[10]ほかのコマンドのマニュアルもほぼ同様に書かれています
[]
この括弧で囲まれている部分は省略可能です
...
この記号は引数がいくつでもいいよって言ってます

つまりこんな感じでコマンドを作ることが出来ます。

$ cat -A -n hogefile fugafile piyofile

主なオプションの説明をします。

-E 行末がどこまで入ってるか分からないから表示して
-n 行数を付けて
-T タブ文字も表示して欲しいなぁ
-v 改行文字も表示して欲しいなー
-A -vETと同じ。改行文字、行末文字、タブも表示します
-s 連続する空行をひとつにまとめる

オプションのFILE部分に - を入れると標準入力になります。fとgというファイルがあって、

cat f - g

このようにコマンドが実行されたときは、fの内容を表示、標準入力の内容表示、ctrl-d(ctrlを押しながらdを押すこと/意味は、入力の終わり)を押したらgの内容が表示されます。 cat 単独で打ったときは --- マニュアル通りの説明をすると、「ファイルまたは標準入力を標準出力にコピーする」 [11] です。 引数が指定されていないときは標準入力になります。標準入力と標準出力を体感してください [12]

[11]cat copies each file (‘-’ means standard input), or standard input if none are given, to standard output.
[12]実際に打ってみよう!! ctrl + c で抜けられるよ!!

ちょっとしたテキストファイルを作るときは

$ cat > hogefile
hoge
fuga
piyo
# ここで ctrl+dを押す

と打つとよいです。

.. index:: tac

tac

さて、catのあとのtac。お察しの通りです。早速、実行してみましょう。ファイルを作るのが面倒なのでechoしてます。

$ echo -e "a\nb\nc" | tac
c
b
a

はい、ファイルの内容を上下逆に出します。1行分の文字の並びを逆にするには、 rev コマンドを使ってください。 誰得魔方陣の例。

$ echo -e "2 9 4\n7 5 3\n6 1 8" | tac | rev

単語単位で逆にするには、

$ tac -r -s '[^a-zA-z0-9\-]' file

revと同じ効果をtacでやるには下記 [13] 。ただし日本語の2バイト文字列も逆にするので化けます。おちゃめさんですね(何

$ tac -r -s '.\|' myfile
[13]単語単位で逆にする例、とrevの効果の例は下記に載っていました。http://bit.ly/SwZTt4
.. index:: nl

nl

行番号を振ってくれるコマンド。単に実行した場合はこんな感じです。

$ nl /etc/issue
     1       CentOS release 6.6 (Final)
     2       Kernel \r on an \m

デフォルトだと、空行には番号が付きません。なお、 cat -b file と同じです。 オプションに -b a を付けると空行でも行番号がつきます。いろいろオプションがあるので値を変更してみてください。

$ echo -e "hoge\n\nfuga\npiyo" | nl -b a -n rz -s " hoge: " -v 3 -w 3
  003 hoge: hoge
  004 hoge:
  005 hoge: fuga
  006 hoge: piyo
.. index:: od

od

主にバイナリファイルを8進数や16進数などで表示するコマンド。デフォルトでは8進数で表示。任意のバイト数をスキップしてそこから表示開始もできます。 なんとなく xxdhexdump を使ってしまって、出番のないコマンドのような...

$ od /etc/issue
0000000 062503 072156 051517 071040 066145 060545 062563 033040
0000020 033056 024040 064506 060556 024554 045412 071145 062556
0000040 020154 071134 067440 020156 067141 056040 005155 000012
0000057
.. index:: base64

base64

データを印刷できる形式に変換するコマンド、とマニュアルには書いてあります。 RFC 4648 [14] に則ってデータを変換するコマンドで、133%データが大きくなります。デコードも出来ます。

$ base64 /etc/issue | base64 --decode -i
CentOS release 6.6 (Final)
Kernel \r on an \m
[14]http://tools.ietf.org/html/rfc4648
.. index:: base32

base32

Coreutils 8.25から登場した base32 です。RFC 4648 のBase32を実装したものです [15] 。デコードも出来ます [16]

$  base32 /etc/redhat-release | base32 --decode
CentOS Linux release 7.2.1511 (Core)
[15]経緯:https://bugzilla.redhat.com/show_bug.cgi?id=1250113
[16]あたりまえだ

てーさい

体裁を整えるコマンドたちです [17]

[17]原題は、Formatting file contents。「てーさい」の元ネタは、てーきゅう(第9期)です。「ていさい!!」にしても良かったかもしれない。ぶおんぶおん!!フルスロットルで楽器をかきならせ!!なんかよくわかんなくなってきた
.. index:: fmt

fmt

テキストファイルの文字を適当に折り返してくれるコマンドです。 デフォルトだと75文字で折り返します。すでに改行されてしまっているテキストファイルでもなんとかしてくれます [18]

[18]wikipediaのサンプルが易しいです。http://en.wikipedia.org/wiki/Fmt
.. index:: pr

pr

ページ単位で印刷用に、ヘッダとフッタを自動的に追加してくれてくれるコマンドです。 RFCみたいな文章がすぐに出来る!プレーンテキストすばらしい!と筆者の脳内で大好評のコマンドです。お試しあれ。ただし使いどころは限定的です。 なお、 pr | pr するとヘッダとフッタが二重につくだけです。こんな感じです。

cat /etc/issue | pr | pr | head -n 12


2015-08-01 10:07                                                1 ページ




2015-08-01 10:07                                                1 ページ


CentOS release 6.6 (Final)
Kernel \r on an \m
.. index:: fold

fold

テキストファイルをぴったりの文字数で改行するコマンド。fmtは空気を読んで、単語をぶったぎらないようにしていますが、このコマンドは空気を読まずにぶった切ります。fmtの様な挙動をさせるには、-sをつけるとある程度空気を読んでくれます。fmtは引用符の中は改行しませんが、このfoldは改行します。

ファイルの一部を出力

.. index:: head

head

ファイル名を引数に取ると、ファイルの最初の10行を表示するコマンドです。 -n 5 で先頭5行を表示。 -c 10KB で先頭10キロバイトを表示。バイナリファイルでもOK [20] [19] 。 -n のあとにマイナス値を打つとどうなるでしょうか。環境にもよりますが...自分でやってみてください。

[19]宗教上の理由でheadコマンドを打ちたくない人は、sed 10q と打ってください。
[20]標準出力に出力して、端末が化けても知らないですよ
.. index:: tail

tail

ファイル名を引数にとると、ファイルの最後の10行を表示するコマンドです。サーバ管理者は毎日打っていると言っても過言ではないです。 -f オプションをつけることによって、引数にとったファイルに対して追加された文字が出てきます。ちなみに複数のファイルを食わせることができるので、アクセスログファイルとアクセスエラーログファイルの両方を tail -f で表示することも可能。パイプでつないで特定の文字列だけ出力することも可能。

tail -f access.log error.log | grep --color -E "(==|192.168)"

ログファイルから"=="または、"192.168"という文字列を抜き出しています [21] 。"=="というのは、やってみてのお楽しみ。

[21]ちなみにgrepの--colorオプションはこのURLで知りました。http://aerith.mydns.jp/regrets/2008/12/tail-color.html

tail -f コマンドと同じような働きをする tailf コマンドがあります。 結論から言うと、最新のCoreutilsを使っているならどっちも変わりありません [22] 。どちらも inotify イベントを受け取って処理するようになっています。 もしも、対象のファイルが消えてしまう、あるいは同じファイル名なんだけどログローテートして中身がリセットされるときは、ファイルを読み直す下記のオプションを使いましょう [23] 。 ついでに8.24から-fしているファイルがリネームされても内容を追っかけることが可能になりました。

[22]coreutils version 7.5でinotifyに対応した模様です。ここを参照しました。http://dev.ariel-networks.com/Members/inoue/tailf/
[23]follow の f らしい。 --max-unchanged-stats=N というオプションがあって、 -F オプションを使った時に、何秒おきにファイルを見に行くか指定することが出来ます。デフォルトは5秒です。一瞬だけ作成されるファイルの中身を書き出しておくときに使えるかも?
$ tail -F filename

tail -n +2 file とすると、fileファイルの1行目だけ削れます。mysqlコマンドに-eでSQLを打ち込むと一行目にカラム名でてくるじゃないですか、あれを削るときに使うんですよ [24] 。 あと、 less でファイルを開いている時に、おもむろに F を押すと tail -f モードに切り替わります。 ついでに、FreeBSD系には、-rというオプションがあります。Coreutilsでは、 tac コマンドで代用してください。

[24]おい、やけに具体的だな
.. index:: split

split

ファイルを分割するコマンドです。 書式は下記です。

split [option] [input [prefix]]

デフォルトで実行するとこんな感じになります。

$ split hogefile
$ ls
hogefile xaa  xab  xac  xad  xae  xaf  xag  xah  xai

1000行ごとに1ファイルを、カレントディレクトリに生成します [25] 。xaa xab ... となっているのは、あとでcatすると元に戻る [26] からです。100行ごとに分割してほしいとか、xxというファイル名いやだというときはこんな感じです。

[25]でかいサイズのファイルのときには注意。たくさんファイルができるよ!!
[26]cat x* する。xの次はy,zと使っていく。最後どうなるのか実験だ!
$ split -l 100 hogefile AA
$ ls
hogefile AAaa  AAab  AAac  AAad  AAae  AAaf

-bオプションで任意のバイト数でsplitすることができます。分割しながら圧縮できる(filterに通す)というオプションもあります [27] [28] [29] [30] [31]

[27]xz -dc BIG.xz | split -b200G --filter='xz > $FILE.xz' - big- (マニュアルより。big-aa.xz, big-ab.xzといったようにファイルが出来上がります)
[28]ディスクの単価が安い現代に需要があるかどうか...
[29]あるって!開発環境とかいつもディスク枯渇してるじゃん!!
[30]開発環境でsplitする用途があるか疑問だにゃあ
[31]脚注で会話するなよ

使いどころが非常に謎ですが、-nオプションの例を示します [32]

[32][練習問題] 何をしているのか、マニュアルを読んで確認してみましょう
$ seq 100 > k; split -nl/7/33 k
20
21
22

8.24から指定した文字でファイルを分離することができるようになりました(-tオプション)。ASCIIのNULL文字でファイルを分割したいというときは split -t '\0'

.. index:: csplit

csplit

「ファイルを文脈ベースで分割する」コマンドです。端的には、特定の文字が出てきたらsplitするコマンドです。使いどころによっては非常に強力なコマンドです。書式は下記。

csplit [option]... input pattern...

下記のようにすると、xx00に文字列を出力し、hogeという文字と遭遇したら、別のファイル(xx01)をつくって、そこに出力します。もとのファイルはそのまま残っています。xx01のファイル名の1行目に hoge という文字が含まれています [33]

[33]長い文章をすぱっと二つに分割する時に便利。日本語文字列でもsplitできる。hoge文字列からのoffsetが使えるのがさらに便利
$ csplit hogedfile /hoge/

さてマニュアルを追ってみましょう。「ファイルがたくさんできるから、最初にディレクトリを作り、その中にcdしましょう」と書いてあります。やっておきましょう。

$ mkdir d && cd d

次に0または5で終わる文字にマッチしたら、そこでまた別のファイルを作ってそこに出力します。 {*} があるので、マッチしたぶんだけファイルが生成されます。出力されている数字は、それぞれのファイルのバイト数です。

$ seq 14 | csplit - '/[05]$/' '{*}'
8
10
15
$ ls
xx00  xx01  xx02

ファイルの中身が、なんとなくどうなっているか分かったところでおわりです。

ファイルの要約系

.. index:: wc

wc

ファイルの行数を知るときによく出るコマンドです。 wc -l が有名すぎて、wc単体の結果についてはmanを引かないと忘れてることが多いです。 wc file したときは、3つ数字がでてきて、それぞれ、行数、単語数、バイト数を出力します。 圧縮されているファイルの文字数を知りたいだけの時は、 bzcat foo.bz2 | wc -c などとするのがよさそう。

-L オプションで、ファイルの中で一番長い行の長さが出ます。また、下記の例では、*.c または *.hファイルのリストから、1行の行数が一番長い行の文字列を表示します。

find . -name '\*.[ch]' -print0 | wc -L --files0-from=- | tail -n1

特定の文字列だけ何回出現しているか知りたいときはこんな感じでひとつ [34]

$ grep -o string file | wc -l
[34]使いどころがありそうであんまりない。でもたまに使うことが、あんまりない
.. index:: sum

sum

BSDのアルゴリズムで16bitのファイルのチェックサムと1024バイト単位のブロック数を表示するコマンド。 -sオプションでSyatem Vのアルゴリズムを使ってのチェックサムと、512バイト単位のブロック数を表示。

$ cat /etc/issue
CentOS release 6.6 (Final)
Kernel \r on an \m
$ sum /etc/issue
28978     1
.. index:: cksum

cksum

ファイル名を引数に取ると、CRC [] のチェックサムを表示します。

$ cksum /etc/issue
2950197414 47 /etc/issue
.. index:: b2sum

b2sum

coreutils 8.26から追加されたコマンドです。BLAKE2 [35] のハッシュ値を出力します。BLAKE2とは、MD5やSHA-1、SHA-2、SHA-3より高速な暗号化ハッシュ関数で、標準SHA-3と同程度の安全性があります [36] [37] 。 md5sumのオプションが使えます。b2sumだけに追加されたオプションは -l, --length です。ハッシュ値の長さを変更することができます。ビットで表現するので8の倍数である必要があります。 --check オプションがある場合は、長さが自動的に決定されるため無視されます。

$ b2sum /etc/redhat-release
6e3cdb9cc64ec29b8a11b9f14f6947cb71897404176c874be6d21359035dbcbc4195af6914d902c553b0bfc8b639b62fa4372b4642efc6dccb4f34d9480b52be  /etc/redhat-release
$ b2sum /etc/redhat-release -l 32
3a140eda /etc/redhat-release
[35]https://blake2.net/
[36]って公式サイトに書いてあります
[37]https://tools.ietf.org/html/rfc7693 にRFCがあります
.. index:: md5sum

md5sum

128bitのチェックサム(またはフィンガープリントまたはメッセージダイジェスト [38] )を計算します。リリースするバイナリと、本番でデプロイされているバイナリが一致しているかどうか確かめる時にたまに使います [39]

[38]この本を読んでいるのにフィンガープリントとメッセージダイジェストを知らないだと!?出直してこい!!と言われないように、知らない人は調べましょう
[39]突然真面目にTipsだしてきたよこの筆者

md5sum が一致するかどうか確かめましょう [40]

$ touch a && md5sum a > a.sum
$ md5sum -c a.sum
a: OK
[40]なお、d41d8cd98f00b204e9800998ecf8427e という謎の文字列をググると47万件ヒットしました
.. index:: sha系

sha系

shaと、sha2で始まるコマンドをまとめました。原文では、 sha1sumsha2 に分かれています。

sha1sum
SHA-1のダイジェストを計算します。md5sumより安全なダイジェストです。SHA-2にとってかわられて徐々に廃止すべき、とマニュアルに書かれています
sha2系コマンド
sha224sum, sha256sum, sha384sum, sha512sumというコマンドがあります。それぞれのビット長のSHAダイジェストを計算します。オプションは、md5sumと同じです。
$ sha224sum /etc/issue
49e10814e2665c2a4040344e927ce4b231152b30c55fb53d8dbb7108  /etc/issue

仕分ですが?

ファイルの中身をソート(仕分)するコマンド群です [41]

[41]原題は、Operating on sorted files。元ネタは、坂本ですが?
.. index:: sort

sort

ファイル中身をソートするコマンド...と書き始めたかったのですが、それ以外にも機能があります。 ファイルを、ソート、マージ、または比較し、表示します。実は3つのモードを持っていて、ソートするモード、マージするモード、ファイルがソートされているかチェックするモードがあります。

チェックオプションのサンプルは下記のようになります。

$ seq 12 > k; sort -c k
sort: k:10: disorder: 10

マージのオプションはこんな感じです。あらかじめソート済みのファイルを流し込んでやるとソートしてくれます。そのため、 seq [42] であらかじめ連続したデータを作っておきます。せっかくなのでheadコマンドで表示してみました。

[42]本書後半で出てきます。連続した数字を出力するコマンドです
$ seq 0 2 10 > a
$ seq 1 2 10 > b
$ head a b
==> a <==
0
2
4
6
8
10

==> b <==
1
3
5
7
9

次に、こんなソートを試します。

$ sort a b
0
1
10
2
3
4
5
6
7
8
9

10は後ろに持ってきたいですよね。そんなときには、-n [43] または-g [44] または-h [45] を付けて下さい。 -n の例だとこんなかんじ。

$ sort -n a b
0
1
2
3
4
5
6
7
8
9
10
[43]マイナスがついている数値でもソートしてくれます
[44]マイナスやプラスの記号がついていてもソートしてくれます
[45]human-numeric-sortです。k,G,Mがついていてもソート可能。CentOS5系だとこのオプションは実装されていませんでした。ご注意

そのほか有用と思われるオプションを一気に解説します。

-u 重複を弾いてくれます
-r 逆順に表示してくれます
-k pos1[,pos2]
特定のカラムにある文字列を対象にソートします。 ps aux の2カラム目を降順でソートした結果:
$ ps aux | sort -nk +2 | tail
-t セパレータを設定します。 -k と合わせて使うことが多いです。使用例は複雑なのでマニュアルを見て下さい
-M Month sortです。月の名前でソートしてくれます
-R Random Sortです。 shuf ればいいと思います [46]
[46]shuf のところで出てくる --random-source が使えます
-V Version Sortです。バージョン番号でソートします
--parallel=n nに並行実行数を入れるとパラレルに実行してくれます。ただし、自動で有効なプロセス数が設定されます。あまり気にしなくていいでしょう。最大値は8です。時代は多コアですけどいいんですかね
.. index:: shuf

shuf

ファイルをshuffleしてくれます [47] 。 もしseqをつかって数字をランダムに出したいときはいったん思いとどまって、下記のようにして下さい [48]

$ shuf -i 1-4
3
1
2
4

同じファイルを共有していれば、同じ結果が返ってきます。つまり、さっき作った k というファイルを使って、あなたと同じランダムな結果を実現してみましょう [49] [50] [51]

$ shuf --random-source=k -e hoge fuga piyo choi
fuga
hoge
piyo
choi

0-9までの数字を50回出すならこれ:

$ shuf -r -n 50 -i 0-9

コインを50回振ってみるならこれ:

$ shuf -r -n 100 -e Head Tail
[47]CentOS5.7な環境でコマンド打ったら出てこない!それもそのはず、CentOSのcoreutilsのバージョンが古いのでした(5.97)。バージョン6.4から新しく加入したコマンドです。
[48]当然、この通りに出てくるわけではありません。--random-source=FILE というオプションもあるのでこだわりたい方はこだわれます
[49]これを人はランダム、と呼ぶのだろうか。謎である
[50]sortにも同じオプションがあります。sortのオプション -R, --random-sort, --sort=random を見てみてください
[51]マニュアルには、 -r または --repeat というオプションがあります。これを使うと、指定した回数だけ繰り返すので、$ shuf -r -n 50 -e Head Tail ができます。誰得。なお、Coreutils 8.21では未実装でした

kというファイルがなかったらどうすんだって?うーん、2.7章にこんなコマンドがあります。seedに与える数によって擬似乱数を生成する関数を作ってそれを実行。決してget_seeded_random関数を単独で実行してはいかん(実際にやった筆者であった)。

get_seeded_random()
{
seed="$1"
openssl enc -aes-256-ctr -pass pass:"$seed" -nosalt \
</dev/zero 2>/dev/null
}

shuf -i1-100 --random-source=<(get_seeded_random 42)
.. index:: uniq

uniq

ソート済みのファイルを引数に取ると、重複行を取り除いたデータを書き出してくれます [52]sort にも -u オプションがあり、 uniq コマンドを単体で打ったときと同じようなことをやってくれます。 よく使うパティーン [53]

$ cat file | sort | uniq -c | sort -nr | head
[52]テストに出るぞー。そういえばsort -uとかありましたね??つまり???
[53]fileに出現した同じ文字列を出現順にランキング表示です。サーバ管理者でこれが出来なかったら落第だ!
.. index:: comm

comm

2つのファイルを比較して、片方にしかないデータ、両方にしかないデータなどを出力してくれます [54] 。 ベン図を書いて、きちんと整理してデータの集計に当たりましょう。実行結果が独特なのでサンプルを載せます。

$ seq 1 3 9 > q
$ seq 1 2 9 > w
$ head q w
==> q <==
1
4
7

==> w <==
1
3
5
7
9
$ comm q w
               1
        3
  4
        5
               7
        9

カラムが3つあります。単独でカラムを取り出したい場合は、 -1 , -2 , -3 というオプションを使います。 また8.26から --total が追加されました。こんな感じです。totalの行は -123 とすると単独で取り出せます。

$ comm q w --total
                1
        3
4
        5
                7
        9
1       3       2       total
[54]通話のアプリじゃないですよ。念のため
.. index:: ptx

ptx

日本語マニュアルによると、「ファイルの内容の整列した索引を生成する」「入力ファイルに含まれる単語の索引を並べ替え、前後を含めて出力します。」 [55] とありますが、使いどころが分からないッ!

[55]http://linuxjm.sourceforge.jp/html/GNU_coreutils/man1/ptx.1.html
.. index:: tsort

tsort

前後関係を与えると、その順にソートしてくれます [56]

[56]マニュアルによると「有向グラフのトポロジカルなソートを行う」と書かれていて、ちょっと何言ってるかよく分からないです

実行例を見た方が早いです。 hogefuga の前にあるといった組を用意してtsortに食わせると順番に並び替えます。ループがあったらどうなるのかな・・・怒られるのかな・・・

$ cat text
hoge fuga
fuga piyo
foo bar
bar baz
baz hoge

$ tsort text
foo
bar
baz
hoge
fuga
piyo

$ cat d
a b
b c
c d
d a
$ tsort d
tsort: d: input contains a loop:
tsort: a
tsort: b
tsort: c
tsort: d
a
b
c
d

テーブルの欄操作

.. index:: cut

cut

ファイルを垂直に切り出します。オプションが必須のコマンドです。 たとえば今月の日曜日の日にちだけ切り出してみましょう [57] 。-c1-2とすると、1から2文字目までが縦方向に切り取られて表示されます。

[57]cal コマンドは今月のカレンダーを表示しれくれます
$ cal | cut -c1-2
Su

 4
11
18
25

csvデータから特定のカラムだけ切り出せます。tsortで出てきたtextファイルに対して2カラム目だけ表示させてみましょう。文字の区切りはスペース1個(-d" ") 、2つめのカラム目を表示(-f2)するオプションを付けます [58]

[58][練習問題] awkでも同じコマンドを作ってみましょう
$ cut -f2 -d" " text
fuga
piyo
bar
baz
hoge
.. index:: paste

paste

ファイルの1行1行を横にひっつけていきます。具体例はマニュアルに書いてあるので読んで下さい。え?読むのがめんどくさい?しょうがないにゃあ。

$ cat num2
1
2
$ cat let3
a
b
c
$ paste num2 let3
1       a
2       b
        c

-s (serial)オプションを付けるとこんな感じ。

$ paste -s num2 let3
1       2
a       b       c
.. index:: join

join

ファイルを横にjoinします。pasteと同じように見えるかもしれませんが、1カラム目が共通の2つのファイルに対してよしなにjoinしてくれます。

$ cat c
00:00 100
00:01 200
00:02 300
$ cat d
00:00 150
00:01 250
00:02 250
$ join c d
00:00 100 150
00:01 200 250
00:02 300 250

とあるサイトのバーチャルホスト別のアクセス数を1分ごとに取るスクリプトを書いて、csvで出してみたりするのがお気に入り。hoge-access.min.logはさっきでてきたファイル c の様な出力になっていて、それを3サイト分、csv形式で出力。あとはexcelにでも突っ込んで1分間ごとのアクセス数を色づけして眺めてみるのが良いのではないでしょうか [59]

[59]ビックデータとかクラウドの時代だとFluentdでなんとかするのが普通かも
$ for h in `seq -w 0 23`
> do for m in `seq -w 0 59`
> do echo $h:$m $(cat hoge-access.log | grep -c $h:$m) ; done ; done | \
> tee -a hoge-access.min.log
$ # などというファイルを三つくらい用意
$ join hoge-access.min.log fuga-access.min.log | \
> join - piyo-access.min.log | \
> sed -e 's/ /,/g' > foo.csv

キャラクタ操作

.. index:: tr

tr

文字の変換と削除を行うコマンド。文字の置換の用途で使うことが多いです。

123という文字列を、3を4に、2を1に、1を6に変換します。 321 という文字列を 456 という文字列に変換するわけではありません。

$ echo 123 | tr 321 456
654

ということは、テキストファイルの文字小文字変換もできます。いずれも同じ意味です [60]

[60]ファイル名を小文字にしたい? mv のコマンドを作って実行すればいいのだ☆
tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ
tr a-z A-Z
tr '[:lower:]' '[:upper:]'

trのtipsを調べると大体でてくるのは改行の削除なんですが。

$ tr -d '\r' < dosfile.txt > unixfile.txt
.. index:: expand

expand

タブを8つのスペースに変換します。おしまい [61]

[61][練習問題] 同じことをsedあるいは他のコマンドで代用してみよう
.. index:: unexpand

unexpand

スペースをタブに変換します。スペースが乱雑に現れてもなんとかしてくれそうです [62]

[62][練習問題] 同じことをsedあるいは他のコマンドで代用してみよう

ファイルリスト表示

.. index:: ls

ls

ディレクトリの中身を表示します。奥深いコマンドです [63] 。 さて問題です。 ls を単独で打ったときはどのような挙動をするでしょうか。おそらくこのような本を買っているということは、説明する必要がないのかなと思いつつ [64] 。個人的によく打つオプションは、 ls -lhatr です。 オプションをさらっとおさらいしましょう。

[63]マニュアルでは7つのセクションに分かれています
[64]解説。カレントディレクトリの中身を表示します。ただし、ディレクトリの中身を再帰的に表示しません。また、 . から始まるファイルも表示しません。アルファベット順で表示します。リストの結果が端に到達したら縦方向に並べます。画面に表示出来ない文字は ? で表示します

どんなファイルを表示するか

-a . から始まるファイルも表示します
-A . から始まるファイルを表示しつつ、 . [65] , .. [66] は表示しません
[65]カレントディレクトリ
[66]一つ上のディレクトリ
-B ~ で終わるバックアップファイルを表示しません
-d ディレクトリのみを表示します [67]
[67]lsしてたくさん普通のファイルがある中でディレクトリだけを表示したいときに使う
-I pattern $ ls -I '*i*' とすると、 i を含むファイルやディレクトリが表示されなくなります
-R ディレクトリを再帰的に表示。下手すると大変なことになるので注意

どんな情報を表示するか

--full-time フルなタイムを表示します。statでいいような...
-g ファイルのownerが省略され、groupのみを表示します
-G ファイルのownerを表示し、groupは表示しません。GNUでないバージョンのlsの互換性のためのオプション
-i inode番号を表示します [68]
[68]inodeってなに?ググりましょう
-h 無味乾燥な数字の羅列であるファイルのサイズを読みやすくしてくれます。ひゅーまんりりーだぶるのhです
-l ファイルのパーミッションやハードリンクの数、owner group、ファイルサイズ、タイムスタンプを表示します

Tip

ハードリンクの数

-l を付けたときこんな感じで表示されます。kというファイルを作っておきます。

$ ls -l k
2875312 -rw-r--r-- 1 nanaka nanaka 27 Nov 29 03:19 k

このとき、nanakaの前の1ってのはなによ、という問題。こうすると分かります

$ ln k l # ハードリンクを張ります。同じinodeを指すファイルを作ります
$ ls -l -i k l
2875312 -rw-r--r-- 2 nanaka nanaka 27 Nov 29 03:19 k
2875312 -rw-r--r-- 2 nanaka nanaka 27 Nov 29 03:19 l

$ rm k # kファイルを消すと...?
$ ls -l -i l
2875312 -rw-r--r-- 1 nanaka nanaka 27 Nov 29 03:19 l # 1 になった!
-n ファイルのグループ、オーナーを数字で表示します [69]
[69]see /etc/passwd
-o -Gとおなじ
-s ファイルに対するディスクの割当量を表示します [70]
[70]手元の環境だと、小さなファイルに関しては4 kbytes が割り当てられていました

ソート順を指定

-c ファイルが作られた(ctime)順でファイルを表示します
-f ソートせずそのまま表示します。-aが有効、-l, --color,-sが無効になっています
-r 逆順にソート
-S ファイルの大きさ順にソートします。デフォルトは大きい順に並びます。小さい順に並べるなら、 -rS
-t ファイルの更新時間(mtime)順にソートします
-u ファイルにアクセスした時間(atime)順にソートします
-U ファイルのソートを行いません。ファイルがたくさん入っているディレクトリで効果を発揮するでしょう
-v バージョンや番号順に表示します。1.2.3と1.2.10を意図したとおりに並べたいときにオススメ [71]
[71]Coreutilsのセクション10.1.4にどのようにソートするのか書かれています
-X 拡張子のアルファベット順で表示します。こんなオプション知らなかったぜ

表示のフォーマットを指定

-1 1ファイル1行で表示します。ファイルの一覧をファイルに書き出すときに使います
-C ファイルを縦方向に表示します。デフォルトの動作です
--color 表示の際の色を決めます。--color=autoがaliasにあるのが普通 [72] 。環境変数の LS_COLORS に色が定義されていますが、いつみても呪文だなあと思います
[72]ディストリビューションによる? なぜ疑問系?
-F ファイル名の一番最後にファイルタイプを示す1文字をひっつけます。/はディレクトリ、@はシンボリックリンク、>はソケットファイルなどなど
--file-type --Fぽいけど実行可能ファイルに関してはファイルタイプを示す1文字がつきません [73]
[73][問題] 実行可能ファイルのファイルタイプを表す1文字はなんでしょう
--indicater-style=word
 wordに、none,slash,file-type,classifyのいずれかを入れると、それぞれ、デフォルトの動作、-pオプション、--file-typeオプション、--Fオプションと同じ意味になります
-k 1024バイト単位でブロックサイズを表示します。-hとか付けると効果がなくなります
-m ファイルをだらだらっとカンマ区切りで表示します
-p ディレクトリの後ろに/を付けます。そういえば、あなたのデフォルトのlsの動作はどうでしたっけ? [74]
[74]読者をゆさぶる筆者の図。多分口元が緩んでいるかもしれないし、そういえば自分のlsの動作ってどうっだったっけ?と自分ではまっている
-x たくさんのファイルが入っているディレクトリを表示したとき、横方向にファイルをソートします。
-T cols 横に並べるファイルの数を指定。 -T 1 にするとファイルの一覧が改行されずに1行で表示しようとするので画面が崩れること請け合い
-w cols 横方向にどれだけ表示するか。-w 1とかすると-1と同じ効果 [75]
[75]マニュアルには引数ないことになってるけど、実際は必要

タイムスタンプの表示形式

--time-style=style
 タイムスタンプのフォーマットを指定できるよ!やったね! [76]
[76]ふえぇ、使いどこが分かりません!

ファイル名の表示形式

-b

例を見てみましょう

$ touch Ctrl-v Enter # ctrl を押しながら
$ # v を押しキーボードから手を離す
$ # 一呼吸おいてEnterを押す。さらにもう一度Enter
$ ls
?
$ ls -b
\r

ファイルの消し方は自分で考えてね!

-N ファイル名をクオートしません。危険が危ない
-q 改行とか表示できない文字を?で表示。デフォルトの動作です
-Q ファイル名を""で囲みます
--show-control-chars
 表示できない文字もそのまま表示します。デフォルトの動作です

余談ですが、 ls を削除してしまった環境でファイルの一覧を得るなら echo *

.. index:: dir

dir

ls -C -b と同じ。

.. index:: vdir

vdir

ls -l -b と同じ。

.. index:: dircolors

dircolors

lsのカラー設定 [77] 。呪文なので唱えて下さい。実行方法が特殊

[77]ぶっちゃけた話、実機のコンソールに入ることは滅多にないのでsshクライアントで色を設定すればよくね?とは思っている。え?Mac?自分で何とかして下さい...
$ eval "$(dircolors [option]... [file])"

-pオプションで設定を見ることが出来ます。

基本的操作

.. index:: cp

cp

ファイルやディレクトリをコピーします。コピーするだけなら問題ないんですが...というところ。細かい仕様を把握しておかないと事故が起きるので [78] 、もし本番環境でやるなら事前テストすることをおすすめします。とくに、 * や、末尾 / のあるなしで効果が変わります。 さて、もう少し細かい挙動を見て行きましょう。原文では、デフォルトだとディレクトリはコピーしないけど、-R,-a,-rオプションをつけると、ディレクトリもコピーするようになるよ、だそうです。シンボリックリンクからコピーするときは、そのシンボリックリンクしかコピーしないけど、--archive(--a),-d,--dereference(-L),--no-dereference(-P),-Hオプションがあるとデフォルトの設定を上書きしちゃうよ、とのこと。

オプションを解説します。

-a,--archive
ファイルの属性と構造をそのままコピーします。というのも、デフォルトでは、コピーしたファイルは、コピーした時点のタイムスタンプになります。
-b,--backup[=method]
バックアップオプションです。上書きや削除が発生する場合に使います。-bの場合は引数を取りません。
-d,--no-deference
シンボリックリンクをコピーするとき、シンボリックをコピーします。ハードリンクの場合も同じくハードリンクとしてコピーします
-f,--force
コピー先に同じファイルがあっても上書き...と思いきや実際の解説はこうなっています [79] 。コピー先の削除またはアンリンクするために、ファイルを開こうとします。それができない場合、削除とオープンを再度試します
-H コマンドで指定されたすべてのシンボリックリンクを辿ります
-i,--interactive
インタラクティブです。ファイルを上書きするとき、上書きするかどうか聞きます。環境によっては、 alias cp -i されています。逆にうざかったりします
-l,--link
ハードリンクをつくります。ディレクトリは引数にとれません
-L,--dereference
シンボリックリンクをすべて辿り、それが指しているファイルやコピーを上書きします
-n,--no-clobber
上書きしないオプションです。-nの前に-iオプションがあった場合は-iオプションを無効化します
-P,--no-dereference
日本語のmanpage [80] と説明が食い違っているのは内緒にしておきましょう。原文では、シンボリックはシンボリックとしてコピーするとあります
-p,--preserve[=attribute_list]
ファイルの属性を保ちつつコピーを行います。 -p オプションで、すべての属性を保ちます。ファイルのオーナー、タイムスタンプなどコピー時に変更しない属性(attribute_list)を選択できます。例えば、 cp --preserve=ownership,timestamp origin copyfile といった感じです。逆にこの属性は保存しなくてもいいや!というときに、 --no-preserve[=attribute_list] というオプションもあります。
-R,-r,--recursve
ディレクトリを再帰的にコピーします。-Rであっても-rであっても効果は同じです
--reflink copy-on-write(COW)を使えるシステムであればCOWを使います。詳細はwikipediaで
-s,--symbolic-link
ファイルに対してシンボリックリンクを作成します。ディレクトリのシンボリックリンクは作ることができません。 ln -s の威厳は保たれました。あ、あとシンボリックリンクをサポートしていないシステムでエラーが出るかも(・ω<)
-u,--update
修正時刻がコピー元と同じかそれより新しい場合、コピーをしません
-v,--verbose
verboseです
[78]すでに存在するディレクトリの中に、コピーするディレクトリのファイルをぶちまけて混ざる事案や、シンボリックリンクを考慮するかしないか事案など
[79]日本語manpageとcoreutilsを適当に混ぜあわせて解説を書いてます
[80]http://linuxjm.sourceforge.jp/html/gnumaniak/man1/cp.1.html 日本語ドキュメントでは、 -P--parent が同じであると書かれていました。試してみたところ -P オプションについては、原文が正しい模様。 --parent オプションの説明としては合っていました

cpの速度

cpの速度と進捗状況が知りたい時があります。こんなときは、pv(pipe viewer) を使いましょう。 yumのextra経由でインストールするか、公式サイトからRPMを落としてきてインストールします。pvの実行例です:

$ pv coreutils-8.22.tar.xz > hoge
5.09MiB 0:00:00 [ 657MiB/s] [================================>] 100%
.. index:: dd

dd

ファイルのコピーとか変換とか行います [82] 。ファイルと言っていますが、デバイスにも対応しています。よくあるディスクのコピーはこんな感じ

# dd if=/dev/sda1 /dev/sdb1

「変換」はどこいったんじゃ!というツッコミもあるかと思いまして、例を挙げます。textというファイルを入力に使います。

$ dd conv=ucase if=text of=test2

これでtextファイルの中身のアルファベットが大文字になります!やったね!! [81]

あと、これまでddがいつ終わるかわからない!という声に応えて status=progress というオプションが8.24から入りました。 コマンド終了時の出力で、でかい数字のバイト表記で単位がよくわからん!という声に応えて、適切なSI単位が8.25から入るようになりました。 3441325000 bytes (3.4 GB, 3.2 GiB) copied こんな感じです。

[81]ucase以外にも、ebcdicやibmといったオプションもあります
[82]なぜddという名前なのかは、'Dataset Definition'の略だとか、'Convert and copy a file'の略でccにしたかったけどすでにそのコマンドがあったのでddにしたとか。真相は自分で確かめよう!
.. index:: install

install

ファイルの属性を指定しつつファイルをコピーすることが出来ます。ファイルをコピーしてからオーナーを変更するという動作がこのコマンドだけでできます。 例をいくつか。まずは、fileというファイルを、ユーザ名user, グループ名groupで/tmpディレクトリにコピーする例:

# install -o user -g group file /tmp/

ディレクトリも作ってくれます。mkdir -p ぽいこともやってくれます:

# install -o root -g root -m 755 -d /hoge/fuga/piyo/choi
.. index:: mv

mv

ファイルの移動を行います。副次的な作用としてファイルの名前を変えることが出来ます。cpのオプションと似ていますので、細かい説明は省略します。

.. index:: rm

rm

「あのころのきおくをけすにはどうやるです?」という妖精さんからの質問に答えましょう。過去にだーくふれいむますたーであった頃の黒歴史を消去するコマンドです [83]

[83]黒歴史をバージョン管理していたら別

前回 ls コマンドの説明の時に作った、改行コードがファイル名になっているファイルを消してみましょう。

$ ls -b
\r
$ rm Ctrl-v Enter # ctrl を押しながら v を押しキーボードから手を離す
$ # 一呼吸おいてEnterを押す。さらにもう一度Enter

消したファイルの一覧を出す例。

$ shuf -i 1-10 | xargs touch
$ ls
1  10  2  3  4  5  6  7  8  9
$ rm -v *
removed `1'
removed `10'
removed `2'
removed `3'
removed `4'
removed `5'
removed `6'
removed `7'
removed `8'
removed `9'

rm -rf /

一般ユーザでスクリプトを実行したとき、空の変数$hogeを対象に rm -rf $hoge ってやってユーザディレクトリの中身を消すってことは、たまにあります。手動で実行する機会はめったにないとは思いたいところではありますが、不運にしてrootで rm -rf / を実行してしまった場合、どうなるかについて。 突然シャットダウンするといったことはありません。/procディレクトリが残るようです [84] [85] 。 さて、突然の rm -rf / を防ぐにはどうするかというと、rmのaliasに --preserv-root をつけておきましょう。ついでに、safe-rmというソフトウエアがあります。これは、rmのラッパであり、システム的に消してはいけないディレクトリを消そうとするとメッセージが現れ消さずに済みます。

[84]筆者も実際にVMware上で rm -rf / をやったことがあります。コマンドが実行できないだけでOS自体は起動している状態でした
[85]参考 http://katsu.watanabe.name/doc/rmrf/

rm undo

いやー、気持ちは分かるんですけどね。わかりますよ。非常によくわかります。undoみたいなコマンドを打てば元通りにして欲しいですよね?大丈夫です。自分でコマンド作ってください。というのは半分冗談で、現実的な答えとしては、ゴミ箱を作ることです。ゴミ箱ディレクトリを作って、mvにエイリアスを貼ります。 alias rm='mv --target-directory=$HOME/.Trash' などとします。 結論をいうと、バックアップ取れ!これに尽きます。

ext3grep

ext3grepというツールがあります。ext3ファイルシステムから文字列をgrepしてくれます。公式ドキュメントいわく、「unmount the partition ASAP ; do not mount it again.」だそうです。ん?バイナリファイル復活させたい?がんばれ!

rmにはaliasが貼ってあることがありまして、 alias rm と打つと、 alias rm='rm -i' と出てくることがあります。 -i はこのファイル本当に消す?と聞いてくるオプションです。 このエイリアスの呪縛から逃れるには、 \rm とバックスラッシュを付けます。さっきのaliasのとき、 rm -rf file とやると、 rm -i -rf file となります。オプションの順序の関係で、あとに置かれたオプションで上書きされるので、 -i オプションは上書きされます。ということで、本当に消す?って聞いてこなくなります。

.. index:: shred

shred

爆ぜたり弾けたりしていた黒歴史を強力に清算するコマンドです [86] 。ファイルやファイルシステム(/dev/sda3など)を引数にとり、何度も上書きを行って黒歴史を清算し、復元される可能性を減らします [87]

真面目に原文を読んでみましょうか。rmしただけでは、本当にファイルが消えてはいません。ファイルの登録情報が消えるだけで、データ本体は消えていません。ディスクの書き込みが激しく、空き容量が少ないデバイスであれば、rmしたあと数秒でその領域を再利用します。上書きされたデータでも、その磁気の痕跡を読み出す機械があるのでデータを復元されてしまうことがあります。 回復できないようにするには、酸で溶かすことです。フロッピーディスクなら容易に溶けますが、ハードディスクは溶けにくいです。そこで、その酸の代わりにご紹介するのがこの shred です。今なら分割金利手数料を [88]

ファイルが消された場所に上書きすることでファイルの復元を不可能にします。注意してほしいことは、ファイルシステムによっては、その方法が通用しないことがあります。NFS経由などでスナップショットをとっていたり、圧縮されているファイルシステムなどです。

使い方はこんな感じです。ファイルを削除したい場合は、 -u オプションを付けてください [89]

$ shred -u secretFile

デフォルトでは3回上書き処理を行います。変更したい場合は -n <回数> を指定してください。 デフォルトの3倍の速さでディスクを上書きする場合は下記のようにしてください。-vは進捗を表示します。

# shred -v -n1 /dev/sda5

SSDに対して下記のように、0のデータ(-z)を書き込むとき、ディスクのコントローラで最適化されてしまい書き込みがブロックされてしまうことがあるので注意 [90]

# shred -v -n0 -z /dev/sda3
[86]劇場版でも爆ぜたり弾けたり。末永く爆発して欲しいですね(おっさん脳
[87]ただし、人々の記憶には残っているでしょう。物理破壊がより有効です(ハードディスクのことです
[88]酸の話はありますけど、金利手数料までは書いてないですよ。多分。原文読めば分かる(あ、投げた
[89]じつは-uオプションに種類があって、デフォルトだと wipesync です。気になった人はマニュアルへGo!
[90]原文でSSDが出てくるとは思わなかった

スペシャルファイルタイプ

シンボリックリンクやFIFO、ディレクトリなどのファイルの操作を行います。

.. index:: link

link

linkシステムコールを経由してハードリンクをつくるコマンドです。

.. index:: ln

ln

ファイル間にリンクをつくるコマンドです。ファイルやディレクトリに対して、ハードリンクや、シンボリックリンク(-sオプション)を作ることができます。 一つ付け加えることとして、シンボリックリンクの上書きオプション(-f)があります。ディレクトリの場合、上書きできず、シンボリックリンクディレクトリの下にシンボリックリンクが出来ているというオチが待っています。

そのほかのオプションとしては、シンボリックリンクからハードリンクを作成するオプションというのがありましたが誰得感強いです。

.. index:: mkdir

mkdir

ディレクトリを作ります。押さえておくべきオプションは二つ。パーミッションを指定する -m 、存在しない2階層以上のディレクトリを作る -p です [91] 。 なお、 -p オプションは、すでに存在するディレクトリを作ってもエラーにならないので、ディレクトリが存在するかどうか判定の判定を横着することができます。といっても、ディレクトリが作れる権限あるかどうか、確認しましょう。

[91]mkdirとは関係ないけど、自分がつくったディレクトリに chmod -x directory とかしちゃ駄目だぞ!おっちゃんとの約束だ!(やったことない人はやってみようというフラグ)
$ mkdir -m 777 dir
$ ls -ld dir
drwxrwxrwx 2 nanaka nanaka 4096  7月 27 01:28 dir
.. index:: mkfifo

mkfifo

名前付きパイプを作ります。パイプとは、 | です [92]

[92]| は、名前なしパイプ(unnamed pipe)です

具体例を示します。

$ mkfifo pipe
$ ls -l > pipe & ; cat < pipe

2行目のコマンドは、わざとワンライナーで書いていますが、別のセッションで試すと感動が増します。 ; の前後のコマンドを逆にしても動作します [93]

[93]"Introduction to Named Pipes" http://www.linuxjournal.com/article/2156
.. index:: mknod

mknod

FIFOや、キャラクタースペシャルファイル、ブロックスペシャルファイルを作ります。 NAME,TYPE,MAJOR,MINOR,MINORに当たる部分は、カーネルソースのドキュメントか https://www.kernel.org/doc/Documentation/devices.txt を参照してください。

$ mknod --help
Usage: mknod [OPTION]... NAME TYPE [MAJOR MINOR]

キャラクタースペシャルファイルとは、キーボードやマウスなどの入力や出力を扱うファイルです。キャラクタースペシャルファイルは1バイトずつの読み出しですが、ブロックスペシャルファイルはある程度の塊としてデータを取り扱います。 下記、一番はじめの b がブロックスペシャルファイル、 c がキャラクタースペシャルファイルです。それぞれハードディスク、zeroです。

$ ls -l /dev/hda
brw-rw---- 1 root disk 3, 0  May 22  2012 /dev/hda
$ ls -l /dev/zero
crw-rw-rw- 1 root root 1, 5  May 22  2012 /dev/zero

MAKEDEV というコマンドでもデバイスファイルを作ることが出来ます。

.. index:: readlink

readlink

シンボリックリンクを引数に与えると、絶対パスを表示します。例えば、PIDから実行されているバイナリの絶対パスを得る方法はこちら [94]

$ readlink -f /proc/$pid/exe
.. index:: rmdir

rmdir

空のディレクトリを削除します。 普段は rm -rf を使うところ。なお、 --ignore-fail-on-non-empty オプションをつけることによって、中身の入っているディレクトリでもエラーを返さず、削除もしません [95]

[95]本書の執筆をサポートしてくれたmtgto氏によると、ホームディレクトリで、 rmdir --ignore-fail-on-non-empty .ssh を実行したところ、警告もなくコマンドが終わってしまって.sshディレクトリが消えてしまったと錯覚する事案が発生したとのこと。みなさんも気をつけましょう
.. index:: unlink

unlink

システムが提供しているunlinkを使ってファイルを削除します。

ファイルの属性を変更

.. index:: chown

chown

ファイルのオーナーとグループを変更します。 --reference=filename でfilenameとそっくりのオーナーとグループになります。シンボリックリンクを追うかどうかのオプションもあり。ファイルのオーナーを変えるので基本的にroot(あるいはsudo)で操作。ちなみに、ownerとgroupのセパレータは : が一般ですが、筆者は . 派。

# chown root:root rootfile # セパレータは、: でも . でも
# chown user. userfile     # 動作します
.. index:: chgrp

chgrp

ファイルのグループを変更。こちらにも --reference オプションがあります。

Tip

uidやgidで指定する方法

ご存知のように、 chownchgrp は、変更するユーザ名やグループ名を引数に与えると指定したユーザ名やグループ名を変更することが出来ます。 uidとかgidで指定できたら、うれしくない?え?できちゃうの?出来ちゃうんですねこれが。uidやgidの数字の前に + を入れれば良いのです []

# chown +1000.+1000 hoge-file
# chgrp +$numeric_group_id fuga-file
# chown +0:+0 /tmp/root-file

[] Coreutilsのマニュアル2.6章に書いてあります。man引いても出てこないです。ユーザ名が数字だったときの対処のため、uid,gidを指定するときは``+``を付けます。ちなみに + はユーザ名やグループ名に使えません。実際に実行してみると「useradd: invalid user name 'love+'」だそうです。Solaris 10は例外。

.. index:: chmod

chmod

ファイルのパーミッションを変更します。数字でパーミッションを指定できたり、相対的な感じでotherのみreadを取り除くこともできます。

# touch hoge
# chmod 777 hoge
# ls -l hoge
-rwxrwxrwx 1 root root 0  7月 27 01:56 2014 hoge

# ls -l file
-rw-r--r-- 1 root root 0  7月 27 01:53 2014 file
# chmod o-r file
# ls -l file
-rw-r----- 1 root root 0  7月 27 01:53 2014 file

MODEの指定はこんな感じです。あとは流れで [96]

[96]おい
Each MODE is of the form `[ugoa]*([-+=]([rwxXst]*|[ugo]))+'.
.. index:: touch

touch

呼吸を止めて一秒なコマンドです [97] 。ファイルのタイムスタンプを変更するコマンドです。中身の無いファイルを作ることも出来ます。 ファイルのatime,mtimeを任意に変更するオプションもあります。 時間の指定の方法は必要であれば調べましょう [98] 。ここでも --reference オプションが使えます。

[97]違います
[98]dateコマンドの日付フォーマットとも違っていて若干もにょる( -t オプション )。 --date= オプションで date コマンドの --date オプションと同じ指定ができます

このディスク容量には問題がある!

ディスク使用状況(Disk usage)です。原文曰く、ディスクは無限のデータ容量を保持できない、だそうです。確かに無限の容量があったら必要ありませんね。duくらいは残して欲しいところ。将来、dfコマンドをたたく必要がなくなる日は来るのか [99]

[99]元ネタは、この美術部には問題がある!
.. index:: df

df

ディスクの空き容量を示します。よく使うオプションは、 df -h です。ディスクの使用量、空き容量がGBやTB単位で出ます。たまに使うオプションは、 df -i です。inodeの使用量を表示します。ファイルをフォーマットするときにinode数が足りるかどうか、心にとめておくといいことがあるかもしれません。そして、inode枯渇はしばしば深刻な問題を引き起こします。 ファイルシステムの形式(ext3やtmpfsなど)を表示するときは、 df -T とします。

実行例です。--o(--output)オプションでいろいろ見れます。必要なカラムだけ表示することもできます。また、例には示しませんが、-lでリモートなマウントは表示しないオプションです [100]

[100]8.21あたりでアクセス出来ないリモートマウントがあるときはハングしたそうですが、8.24で修正
# df
Filesystem     1K-blocks    Used Available Use% Mounted on
devtmpfs          241308     140    241168   1% /dev
tmpfs             251108       0    251108   0% /dev/shm
/dev/vda1       20511356 2025232  17437548  11% /
# df --o
Filesystem     Type      Inodes IUsed   IFree IUse% 1K-blocks    Used
devtmpfs       devtmpfs   60327   529   59798    1%    241308     140
tmpfs          tmpfs      62777     1   62776    1%    251108       0
/dev/vda1      ext4     1310720 65729 1244991    6%  20511356 2025232
# (続き)
   Avail Use% File Mounted on
  241168   1% -    /dev
  251108   0% -    /dev/shm
17437548  11% -    /
.. index:: du

du

カレントディレクトリにあるファイルのサイズをすべて表示します。 du -h さえ覚えていればなんとかなります。 -h は、ひゅーまんりりーだぶるのhです。 個々のファイルサイズはいらないよ、というときはsummarizeオプションをつけて du -hs で所望の結果。 du -h /home/* こういうことをすると、誰が一番ディスクを使っているかランキングをとることです [101] [102] 。 筆者が一番使うオプションは、 du -hcs * です。 * をつけると、カレントディレクトリにある各ファイルとディレクトリの容量を表示してくれます。 -c は、トータルの容量を教えてくれます。

[101]さあここで sort の出番ですね
[102]ファイルがでかいと、i/oを食うので注意
.. index:: stat

stat

ファイルが作られた日時や編集された時間を表示するコマンド、と思いきや、ファイルのあらゆる属性を表示するコマンドです。と、思いきやほとんどlsで事足りるのでした。statでとれる属性は、割り当てられているブロックサイズやinode番号、atimeのエポックタイム数値などが取得できます。API的に取得するにはちょうどいいコマンドです [103]

$ stat hoge
  File: 'hoge'
  Size: 5335124         Blocks: 10424      IO Block: 4096   regular file
Device: ca01h/51713d    Inode: 114         Links: 1
Access: (0664/-rw-rw-r--)  Uid: (  500/ec2-user)   Gid: (  500/ec2-user)
Access: 2014-04-17 19:16:38.329808922 +0000
Modify: 2014-04-17 19:21:24.705872432 +0000
Change: 2014-04-17 19:21:24.705872432 +0000
 Birth: -
[103]Birthってなんでしょうね?
.. index:: sync

sync

メモリにバッファされているデータをディスクに書き込みます。サーバを haltreboot あるいは shutdown する前に sync; sync; sync するという文化で年齢が分かるかもしれません。 なお、 --help , --version 以外のオプションは無視されます [104]

[104]と、思いきや8.24からオプションが追加されました。マジで!?こんなマイナーなコマンドに!? --dataと--file-systemです。ファイルを指定して、どのようにsync(sync,syncfs,fsync,fdatasync)するのか指定できます。
.. index:: truncate

truncate

ファイルのサイズを減らしたり増やしたり。ボクと契約して10Mのダミーファイルを作ってよ!と言われても慌てず騒がず truncate -s 10M file して提出して下さい [105] 。ファイルの中身を空にすることもできますが、 $ > file でいいよねという風潮[脳内調べ]。

[105][問題] 提出したデータの中身はどうなっているでしょうか。確認してみましょう

文字を表示

文字を表示するコマンドです。

.. index:: echo

echo

与えられた文字を標準出力に書き出します。デフォルトだと、最後に改行が入るので、ハッシュ値を作るときには注意して下さい。改行が入らないようにするためには、 -n オプションを。 \n (new line) といった特殊文字を出力するためには下記のように。

$ echo -e "a\nb\nc"
a
b
c
.. index:: printf

printf

C言語のprintfに似たフォーマットで文字列を出力します。たとえばこんな感じ

$ printf "%d" "'a"
97
.. index:: yes

yes

Ctrl-c(ctrlを押しながらcを押す。つまりkillが実行)されるまで、引数に渡された文字列を延々と表示します。 最後はkillされる宿命なので、終了コードは必ず1になります。「イエッス、アスミス」はこのようにしてください。

$ yes asumisu

hostというホストへのネットワークの速度を測りたい場合はこちらです [107] [108]cp のところででてきた pv [106] が再登場します。

yes | pv | ssh host "cat > /dev/null"
[106]pipe viewer
[107]http://www.commandlinefu.com/commands/view/4434/live-ssh-network-throughput-test
[108]yesというかマシンの性能によるんじゃないかなぁ、などと思う今日この頃

条件

.. index:: false

false

何もしない、成功しない。戻り値は 1 です [109]$? は、直前に実行したコマンドの戻り値を拾ってくれる変数です。

[109]C言語と違うので混乱します
$ false ; echo $?
1
.. index:: true

true

何もしない、成功。戻り値は 0 です [110] 。シェルスクリプトのif文で、何もしないときに使います。trueと同じ意味のビルトインコマンド : で代用することがあります。

[110]混乱してきましたね。実際ifを実行するときは、脳内で真か偽かで判断しましょう。1か0とか考えていると混乱します
$ true ; echo $?
0

ここで終わるのも何なのでソースを見てみましょうか [111] 。mainの部分です。

[111]https://github.com/coreutils/coreutils/blob/master/src/true.c
int
main (int argc, char **argv)
{
  /* Recognize --help or --version only if it's the only command-line
     argument.  */
  if (argc == 2)
    {
      initialize_main (&argc, &argv);
      set_program_name (argv[0]);
      setlocale (LC_ALL, "");
      bindtextdomain (PACKAGE, LOCALEDIR);
      textdomain (PACKAGE);

      /* Note true(1) will return EXIT_FAILURE in the
         edge case where writes fail with GNU specific options.  */
      atexit (close_stdout);

      if (STREQ (argv[1], "--help"))
        usage (EXIT_STATUS);

      if (STREQ (argv[1], "--version"))
        version_etc (stdout, PROGRAM_NAME, PACKAGE_NAME, Version, AUTHORS,
                     (char *) NULL);
    }

  return EXIT_STATUS;
}

EXIT_STATUSは、ご覧のとおり。

#ifndef EXIT_STATUS
# define EXIT_STATUS EXIT_SUCCESS
#endif

おっと、ここで、 false のソースコード見てみましょうか [112]

[112]https://github.com/coreutils/coreutils/blob/master/src/false.c
#define EXIT_STATUS EXIT_FAILURE
#include "true.c"
.. index:: test

test

コマンドの戻り値を判定して条件分岐します。コマンドとしては、 $ test expression や、ビルトインコマンドとして [ expression ] が利用できます。expressionについては、shellのマニュアルに書いてあります。指定されたファイルが存在するか、数値の大小比較などができます。

$ HOGE=str
$ if [ "xstr" = x$HOGE ] ; then
>   echo $HOGE
>   else
>   echo $HOGE is not str
> fi
str

HOGEという変数がstrかどうかを比較するサンプルです。もし、xがなくて、$HOGEが空だと [ str = ] となってしまい、syntax errorになるので慣習としてxを付けています。 [] の返値が1か0で条件分岐します。つまり、 [ "xstr" = x$HOGE ] というコマンドが実行可能です [113] 。そんなわけで、 [ というコマンドがあるんですよ...もちろんコマンドなので、 [ のあとにスペース入れないといけませんよ...きこえますか...きこえますか...あっ、見られてますね... [114]

[113]補足しておくと、 test "xstr" = x$HOGE というコマンドと等価です
[114]とくにオチはない
[115]なお、coreutils自体に``[``コマンドがあり、testコマンド読み込んで``[``コマンドをビルドするlbracket.cがあります

expressionの比較のサンプルです。なぜ eq とか ne とかしてしまったんや。 > にするとリダイレクトに食われるからか。仕方ないね。

$ ONE=1
$ TWO=2
$ ICHI=1
$ test $ONE -eq $ICHI ; echo $? # 数字が一致しているとき真(equal)
0 #
$ test $ONE -ne $ICHI ; echo $? # 数値が違うとき真(not equal)
1 #
$ test $ONE -gt $TWO ; echo $? # ONE > TWO のとき真(grater than)
1 #
$ test $ONE -lt $TWO ; echo $? # ONE < TWO のとき真(less than)
0 #

file,file1,file2というファイルがあった場合は、

$ touch file1
$ touch file2
$ test file1 -nt file2 ; echo $? # file1がfile2より新しいとき真(newer then)
1 #
$ test file1 -ot file2 ; echo $? # file1がfile2より古いとき真(older than)
0 #
$ test -e file ; echo $? # fileが存在するとき真
0 #

文字列のとき

$ STR=string
$ test $STR ; echo $? # $STRになにか入っていたら真
0 #
$ test $STR = $STR ; echo $? # 文字列比較。==でも可
0 #
$ test $STR != $STR ; echo $? # 文字列不一致
1 #

なお、expressionの先頭に ! をつけると否定、 expression -a expression-a はAND条件、同様に -o はOR条件になります。 ファイルのタイプ(スペシャルファイルか、シンボリックリンクか、ディレクトリか、ファイルかどうかなど)を判定することもできます。

.. index:: [

[

manはありませんが、コマンドとして存在します。ソースもあります。貼り付けときますね [116]

[116]https://github.com/coreutils/coreutils/blob/master/src/lbracket.c
#define LBRACKET 1
#include "test.c"
.. index:: expr

expr

式を評価します。といっても最近はもっぱら $()$(()) を使っています。例は、 join の時に出てきています。括弧二つの方は何となく数値計算ができるので電卓代わりに使っています。 echo $((12*34)) といった感じです [117]

[117]そして始まる bc との宗教戦争

リダイレクション

シェルのリダイレクションです。コマンドとしては1個しかないとはこれいかに [118]

[118]|> はシェル組み込みなので、しゃーなしだな
.. index:: tee

tee

出力を複数のファイルやプロセスに渡すコマンド。teeはTのことで、T型に出力という意味です [119] 。 コマンドの結果をファイルに書き込むときよく使うリダイレクション > file のとき、何が出力されるのか、別の端末を開いてtailするまで分かりません。ファイルにも書きつつ、標準出力にも出力するときに使います。 join のサンプルのところで出てきているのでサンプルはそちらを参考にして下さい。なお、 -a オプションはファイルへの追記を意味しています。

[119]Tの字形をみるとわかってくる

複数のファイルやプロセスに渡せるということなので、こんなコマンドも実行可能です。ファイルをダウンロードして標準出力に投げて、sha1sumとmd5sumでハッシュ値をとり、dvd.isoにダウンロードしたファイルを書き出し。

wget -O - http://example.com/dvd.iso \
  | tee >(sha1sum > dvd.sha1) \
        >(md5sum > dvd.md5) \
  > dvd.iso

8.24からエラーが起きた時、どの出力に書き出すか指定できるようになりました(--output-errorオプション)。

ファイル名の操作

ファイル名の操作をします。

.. index:: basename

basename

ファイル名からディレクトリや拡張子を取り除きます。

$ basename /usr/local/bin/sh
sh

スクリプトの中で、 basename $0 と書くとそのスクリプト自身のファイル名が表示されます。ついでに、 basename $0 .sh と書くと、.shを除いたファイル名が表示されます。

.. index:: dirname

dirname

ファイル名やディレクトリパスを引数にとり、ファイル名の最後の一部を取り去ります。実際には、ファイルパスの最後のスラッシュを取り去る挙動をします。ファイルがあるかどうかのチェックはしていません。

$ dirname /usr/local/bin/
/usr/local/bin
$ dirname /usr/local/bin/bash
/usr/local/bin
$ dirname /usr/local/bin/hoge
/usr/local/bin # !?
$ dirname /etc/etc/etc
/etc/etc # うーん
.. index:: pathchk

pathchk

ファイル名のSAN値をチェックします。正確には、ファイル名を引数にとって、ファイル名をほかのシステムに持って行っても大丈夫かどうかチェックします。意訳すると、こんな感じです:

  • パーミッションが関係でディレクトリの中身がみることができない
  • ファイル名長すぎ
$ pathchk a<snip>a
pathchk: a<snip>a: File name too long
.. index:: mktemp

mktemp

一時的な空のファイルやディレクトリを作ります。bashスクリプトを書くときに、安全のため、使った方がいいけど、使わなくても何とかなります [120] 。 既存のファイルを重複しないファイル名やディレクトリを作ってくれます。Xと書くと [121] その部分に適当な文字をあてがってくれます。

[120]一時ファイルを作るときにmktempを使っていると、ちゃんとしているなあという印象を与えることができます[脳内調べ]
[121]Xは3文字以上じゃないと怒られるので注意

実際に使うときは、こんな感じです。作られたファイル名を取得します。

$ TMPFILE=$(mktemp hoge-XXXXXXX.txt) # この時点でファイルが作られます
$ echo $TMPFILE
hoge-82TiSmn.txt

その他オプションは下記の通り

-u XXX XXXの長さだけ、ある程度ランダムな文字を表示します
-d XXX ディレクトリを作ってくれます
-q ランダム文字を表示します。ファイルは作られません。ランダムな文字列がほしい時に使うといいんじゃないでしょうか
-p dir dirディレクトリの下にファイルを作ります
.. index:: realpath

realpath

相対パスやシンボリックリンクを絶対パスに直します。Coreutils 8.15 (2012-01-06)より加入。

$ realpath /tmp/../tmp/../tmp
/tmp
$ realpath hoge
/home/ec2-user/hoge

わーきんぐの状況

働きましょう [122] 。カレントディレクトリの状況を示します [123]

[122]ちっちゃくないそうである。なお、この章のタイトルは Working Context
[123]某所の邦訳を見てみると「作業中の状況」となっており、まあ、だいたいあってます
.. index:: pwd

pwd

「ここはどこ?」コマンドです。今いるディレクトリを表示します [124] 。もうこれ以上説明しなくちゃダメカナ?ダメダヨ?

[124]Print Working Directory

オプションは下記2種類。

-L --logical と同じ。 pwd のデフォルトの動作と覚えておけば不都合はなし
-P --physical と同じ。シンボリックリンクをたどる。つまりこんな感じ
[user@hostname]# ln -s /usr/local/apache2/logs /var/log/httpd # symlink
[user@hostname]$ cd /var/log/httpd
[user@hostname /var/log/httpd$ pwd -L
/var/log/httpd
[user@hostname /var/log/httpd$ pwd -P
/usr/local/apache2/logs
.. index:: stty

stty

端末のキャラクターを表示したり変更したりするコマンドです。 端末とは、役所に設置されている住民票発行装置や、銀行のATMを想像してみてください。とあるサーバの画面を離れたところにある画面に表示させているというイメージです。表示させて且つ操作することができます。パソコンに画面つなげて表示して操作するのも端末、sshでリモートログインしているときも端末 [125] 。筆者はだいたいそんなイメージで端末という言葉を解釈しています。もっと年のいったおっさんが説明すると、もうちょっと古い端末を引っ張り出してきてボーとかテレタイプといった話をしだすと思います。

[125]sshだとエミュレータになりますけどね。端末エミュレーターでぐぐると深い話が垣間見れるのではないでしょうか。ktermとかxtermとか

んでまあ、何が言いたいかというと、その端末の表示を変更するコマンドがこれなんです。 原文を読んでみましょう。ライン設定が与えられていないとき、sttyはボーレートを表示します。え?マジで?

$ stty
speed 38400 baud; line = 0;
-brkint -imaxbel

baud(ボー)の登場です [126]

[126]ボーは、搬送波に対する1秒間あたりの変調の回数と定義される(wikipediaより)。そして、1baudは1bpsと一致するかもしれないし、しないかもしれない。詳しくはwikipediaあたりを参照してください。

中断しちゃいました。続きです。sttyはシステムがサポートしているライン制約ナンバーや stty sane で設定されている値から変更された設定を表示します。 デフォルトでは、モードを読み込みや設定は、端末上の標準出力で実行されます [127] 。--fileオプションで変更可能です。 sttyは引数ではないたくさんのオプションがあります [128]

[127]よく考えなくても当たり前というかなんというか
[128]19.2.1から19.2.7まで解説に割かれています

主なオプションは下記です。

-a --allと同じです。実行してみましょう
$ stty -a
speed 38400 baud; rows 38; columns 79; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z;
rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts -cdtrdsr
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon
-ixoff -iuclc -ixany -imaxbel -iutf8 opost -olcuc -ocrnl onlcr -onocr
-onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 isig icanon iexten
echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke
-F device --file=deviceと同じ。deviceに繋げます
-g --saveと同じ。ほかのsttyにつなぐため設定を保存しておくオプション

原文には、そのほかにオプションがたくさん載っているので、気になったら見てみましょう。

.. index:: printenv

printenv

環境変数を表示します。それだけです。

.. index:: tty

tty

スタンダートインプット上のターミナルのファイル名を表示します。打ってみましょう。

$ tty
/dev/pts/0

上記の結果は、さくらのVPSサーバにログインして tty コマンドを打った結果です。さらに別の端末から同じサーバに入り、同じコマンドを打ってみましょう。

$ tty
/dev/pts/12

通常ならば、1になります。ここのサーバでは、 screen が立ち上がっていて、1から11まで使っていました。つまり今回は、12に割り当てられました。詳しくはスペシャルデバイスファイルでぐぐってみましょう。

ユーザの情報

ユーザやグループなどの情報を表示します。

.. index:: id

id

ユーザのidを表示します。打ってみましょう [129]

[129]value-server(レンタル共用サーバ)での結果。16人目のユーザなのかもねー。ちなみに、本当に「hoge」というユーザでユーザ名を作りました
$ id
uid=10016(hoge) gid=20000(hpusers) groups=20000(hpusers)

筆者がこのコマンドを使うときは、あのユーザwheelに入ってたっけ?と確認するときに使います。たとえばこのような感じ

$ id ellen_jeager
# 結果省略

なお、オプションは以下の通り

-g --groupと同じ。グループIDを表示します
-G --groupsと同じ。グループidと補助グループidを表示
-n --nameと同じ。ID番号じゃなくて名前で表示。-uか-g、または-Gが必須
-r --realと同じ。ID番号じゃなくてrealで表示。-uか-g、または-Gが必須。実行してみたけど、id番号しかでてこなかったぜ
-u --user と同じ。ユーザIDのみを表示
-z --contextと同じ。セキュリティーコンテキストを表示。SELinuxが無効になっていたら警告を表示してreturn 1する。

所属しているグループは、ログインした後に変更を加えても、今接続しているセッションには適用されないよ!ログインし直すと適用されるよ!と書いてあります [130]

[130]かなり意訳
.. index:: logname

logname

現在のログイン名を表示します。utmpファイル [131] から情報を読み出します。このファイルは、システムの現在の状態のすべてのアカウント情報を管理していて、システムが起動してからの時間 [132] や、システムイベントやユーザのログイン、ログアウトの情報が記録されています。オプションは、 --help--version のみです [133]

[131]/var/run/utmp か /etc/utmp にあります
[132]uptimeコマンドを使って読み出します
[133]--version を打ってみたら、「Written by FIXME: unknown.」とでました
.. index:: whoami

whoami

わたしはだあれ?コマンド。現在のユーザidに関連づけられているユーザ名を表示します。同じコマンドは、id -un

.. index:: groups

groups

所属しているグループ名を表示します。打ってみましょう。引数にはユーザ名を入れます。

$ groups hoge root
hoge : hpusers
root : root wheel rvm

id -Gn と同じコマンドです。

すべてのユーザ・グループを見るには、 getent group します。

.. index:: users

users

現在ログインしているユーザの名前を表示します。実行してみましょう。

$ users
fairy fairy fairy fairy fairy fairy fairy fairy fairy fairy fairy fairy fairy fairy

妖精さんだらけーーー [134] 。 すべてのユーザ・グループを見るには、 getent group します。

[134]はみ出してるし。本当は自分の名字が並んでいただけでした。それだとおもしろくないので妖精さんを並べてみました。英語表記これであってるのかしら。無難に yo-say-san とかにしておいた方がよかったかも?生足魅惑のマーメイド??つまり上半身は魚???妖精さんの上半身は魚…ッ ざわ・・・ざわ・・・
.. index:: who

who

現在ログオンしているユーザの情報を表示します。コマンドの例は下記です。

who [option] [file] [am i]

原文をよく見ると、「am i」だけ斜体になってないんですよね。ということで実行してみましょう

$ who am i
chiba    pts/11       2013-06-23 17:57 (:pts/12:S.10)

だいたい実行結果が見えてきたところで、オプションです。

-a --allや -b -d --login -p -r -t -T -u と同じです
-b --bootと同じです。システムが最後に起動した日時を表示します。uptimeだと起動してからの時間が表示されます。意外と便利かも
$ who -b
system boot  2012-12-14 05:16
-H --headingと同じです。表示の際にヘッダをつけます
-l --loginと同じです。訳すのが面倒だったので実際に打つとこんな感じです [135]
[135]以前契約していたvalue-serverで試しました。うすうす気づいていたのですが、これ、物理コンソールにrootでログインしっぱなしになってないですかね
$ who -l
LOGIN    tty4         May 14 14:01              5500 id=4
LOGIN    tty2         May 14 14:01              5481 id=2
LOGIN    tty3         May 14 14:01              5491 id=3
LOGIN    tty1         May 14 14:01              5472 id=1
LOGIN    /dev/ttyS1   May 27 19:30             48033 id=v/tt
LOGIN    tty5         May 14 14:01              5503 id=5
LOGIN    tty6         May 14 14:01              5514 id=6
--lookup utempに記録されているホスト名からDNSルックアップしようとします。デフォルトでは機能しません。インターネットアクセスをするので表示するまでにちょっと時間がかかるからです
-m who am i と同じです

ここで、manコマンドを引きましょう。すると、

who [OPTION]... [ FILE | ARG1 ARG2 ]

コマンドの書式はこうなってますね。もうちょっと読み進めましょう。すると、

If ARG1 ARG2 given, -m presumed: 'am i' or 'mom likes' are usual.

だそうです。あとは察してください [136]

[136]3分くらい遊んで飽きる
.. index:: pinky

pinky

マニュアルに載っていません [137] 。でも man pinky すれば出てきます。

[137]Coreutilsのリポジトリに、TODOというファイルがありまして、その中のTODOの項目に入っています

なにをするコマンドかと言えば、 finger の簡易版のコマンドです。 finger って何ですか?良い質問ですね。ユーザの情報を探すプログラムです [138] 。実行してみましょう [139]

$ finger
Login     Name       Tty      Idle  Login Time   Office     Office Phone
root      root       pts/0          Jul 28 13:39 (hostname.example.com)
$
[138]user information lookup program (man fingerによる)
[139]この実行結果に違和感を感じないのであれば、分かっていないか、分かってる人に分類できます

manの結果はこんな感じです(抜粋)。

SYNOPSIS
  finger [-lmsp] [user ...] [user@host ...]

fingerプロトコルを喋れるサーバにfingerすることができますが、もうそんなホストはないんじゃないんでしょうか。 finger linux@kernel.org ってやると 最新のカーネル情報をとれるらしいんですが、もういないみたい [141] 。fingerプロトコルについては、RFC1288 [140] を参照。

[140]https://tools.ietf.org/html/rfc1288
[141]https://www.kernel.org/finger_banner っていうのがありますね

対してpinkyはこんな感じ。user@hostがないですね。

SYNOPSIS
    pinky [OPTION]... [USER]...

単に実行してみます。

$ pinky
Login    Name       TTY      Idle   When         Where
root     root       pts/0           Jul 28 13:39 hostname.example.com

pinkyっていうのは、指に対しての小指という意味で名づけたのでしょう。おしまい。

システム~from date to uptime~

システムの情報を変えたり表示したりします [142]

[142]原題は、System context。元ネタは、ひなろじ~from lock & Logic~。三者三様とうらら迷路量を昇華した上澄みだけが輝く尊いアニメだと思ってるんだけどどうだろう(何言ってんだこいつ
.. index:: date

date

役割は大きく分けて2種類あります。時刻を表示することと、時刻を設定することです。時刻の表示から説明すると思った?残念、時刻の設定でした! [143]

[143]残念さやかちゃん

時刻の設定。よく忘れます:

date [-u|--utc|--universal] [ MMDDhhmm[[CC]YY][.ss] ]

-u は使う機会はないでしょう [144] 。6月25日の23時34分45秒に設定したいときはこのように [145]

[144]amazon awsだと引っかかりそうな。と思ったけど、日にちずれてることもないから、どうでもよかった
[145]正確な時間がズレまくっていると、ntpdでも合わせてくれないので、だいたい近い日時に合わせましょう。ただし、時間を巻き戻す場合は、アプリケーションで不整合が起きることがあるので要注意。本番環境で気軽にやるなよ!!!
$ date 06252334.45

時刻の設定はこのへんにして、単独で実行してみます。

$ date
Mon Jun 24 00:34:47 JST 2013

表示形式を変更したり、1ヶ月後といった相対的な日付も出力することができます。オプションをいちいち説明するよりは実例を見たほうが早いです [146]

[146]完全に執筆してる時期ばれてますやん
$ date +%Y%m%d
20140727
$ date '+%Y-%m-%d %H:%M:%S'
2014-07-27 04:48:10
$ date -d '1 hours ago' +%X
23時20分22秒 # 日本語ロケールの場合こうなる

基本的な書き方はこれでマスターです。例えば、%Yと書くと今年の西暦である2014を表示、%yで西暦の下二桁、つまり、14を表示します。 気をつけるところは、%が出現する一番最初に「+」の記号をつけること。さもないと、エラーになります。 %に続く文字については、manを見ましょう [147] 。 次に、-d(または--date)オプションの説明をします。-dには、1時間前や1時間後、明日や先月などを指定することができます。「last month」と書けば、現在の時刻を基準とした先月の日時を表示することができます。適当に書いても結構柔軟に対応してくれます。ついでに指定できる文字列は、first,second,...,twelth,last,this,first,next,tommorow,yesterdayなどです。さて、この後は「21.1.7 Examples of date」を追っていきます。

[147]%Y%m%d %H%M%Sあたりを覚えておけば、たいてい事足ります
date --date='2 days ago'
おとといの日付を指定します
date --date='3 months 1 day'
3ヶ月と1日後の日付を指定します
date --date='25 Dec' +%j
1月1日から指定日までの日数を表示します
date '%B %-d'
月の完全名と月を表示します。%Bの部分はロケールによってJulyとか7月などに変わります。%-dの部分は、0埋めをしません。7月6日であれば、6となります。%dだけだと06になります
date --set='+2 minutes'
現在のシステムの時刻を2分進めます。root権限が必要です。システムの時刻を変更するときは注意だぞ!
date +%s
1970年1月1日からの秒を表示します [148]
[148]俗にいうエポックタイム。-dで日付を指定すればその時点のエポックタイムを表示します
date -d @946684800
1970年1月1日から経過した秒数を理解しやすい感じで表示してくれます [149]
[149]Coreutils 5.3.0から機能です。これ以前だと、 -d '1970-01-01 UTC 946684800 seconds'とする

ここで問題です。先月の最終日の日にちを出すワンライナーを作ってください。例えば、4月なら3月は31日まであるので、「31」を表示します。 ここで答えを書いてしまうとすぐ見えてしまうので、この本の「おわりに」の脚注に載せました。

dateとcrontab

crontabに date +%Y%m%d と書くと正しく動作しません。 % をエスケープしないといけないんだよ、な、なんだってーΩ Ω 筆者もハマったことがあります。 date +\%Y\%m\%d と書きましょう。これで動く!まあ、こうやって書くのが面倒ならスクリプトファイルにして、それを呼び出せばいいんですけど。

時刻合わせ

サーバの製造元が日本でない場合、製造した現地時間に合わせてあったりします。このとき、OSのisoイメージからマウントして、サーバにOSをインストールすると、BIOSの時刻を引っ張ってくるので時刻がズレます。そういえば、BIOSであわせるの忘れてた(・ω<)となります。仕方ないので最近はこのようにしてます。当たり前ですけど、時刻がずれている場合は、OSをインストールしたらすぐ時刻をあわせましょう。

# ntpdate <ntp server name OR IP address> && \
> hwclock --systohc && hwclock --adjust

$ cal 9 1752

dateつながりで、カレンダーを表示するcalコマンドです。これは、ただのトリビアです。 GNUにはgcalという高機能なカレンダーコマンドがあります。詳細はこちらをご覧ください: http://www.gnu.org/software/gcal/

.. index:: arch

arch

uname -m と同じ。実行してみましょう [150]

$ arch
x86_64
$ uname -m
x86_64
[150]$ strace archしてみたら、uname呼んでました
.. index:: nproc

nproc

有効なプロセッサの数を表示します。実行してみましょう [151] [152]

$ nproc
32
[151]以前契約していたvalue-serverでの実行結果。こんなサーバなかなかお目にかかれないなぁ。/proc/cpuoinfo見てみたら、本当にCPUが32個あった
[152]ついでに、このコマンドはcoreutils 8.4あたりの比較的新しいバージョンに入っているみたいです。デフォルトのCentOSの5あたりだと入ってないかも

クールな例 [153]

[153]https://www.df7cb.de/blog/2010/nproc.html
$ make -j $(nproc)
.. index:: uname

uname

現代語訳すると「coreutilsの作りしコマンドよ、我が前にシステム情報を表示せ、uname」になるんですかね [154] 。実行してみましょう [155]

[154]その前に、現代語訳じゃないでしょ。アニメ始まったの1999年だから15年くらい前だぜ。今思うと十分に中二病ですな、このセリフ
[155]本当は1行で出力されます
$ uname -a
Linux e2.valueserver.jp 2.6.32-358.6.1.el6.x86_64
#1 SMP Tue Apr 23 19:29:00 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

オプションは下記の通り。

-a すべての情報を表示。32bitか64bitが分からなかったらその部分は表示しないよ!
-i ハードウエアのプラットフォームの名前(x86_64とか)を表示。カーネルによって情報が作られていないときは unknown って表示します
-m ハードウエアの名前を表示(x86_64とか)
-n ネットワークノードのホスト名を表示(e2.valueserver.jp)
-p 命令セットアーキテクチャとかISAと呼ばれるプロセッサの型を表示。 unknown だったらオプションの -i と同じ理由
-o OSの名前を表示(GNU/Linux)
-r カーネルリリースを表示(2.6.32-358.6.1.el6.x86_64)
-v カーネルバージョンを表示(#1 SMP Tue Apr 23 19:29:00 UTC 2013)
.. index:: hostname

hostname

コマンド単体で実行するとホスト名を表示します。ホスト名を変更する場合は、rootユーザで、引数に新しいホスト名を指定して実行します。一旦ログアウトしてログインすると、ホスト名が変更されています。再起動して元に戻ってしまうのを防ぐために、設定ファイルの変更も忘れずに [157] 。あと、hostnameを拾って起動しているプロセスにも注意を払っておきましょう [156]

[156]mysqlとか
[157]hostsファイルも気にしてあげてください
.. index:: hostid

hostid

ホスト識別子を16進数で表示します。ソースを見ると分かるんですが、gethostid関数を呼んでいます。試しにDigitalOceanのサーバでやってみるとこんな感じ。

$ hostid
00000000

なんでやねん。原文の例にはこうあります。

For example, here’s what it prints on one system I use:
$ hostid
1bac013d
.. index:: uptime

uptime

現在の時間とシステムが起動してからの時間と、ログインユーザの数と、ロードアベレージを表示します。ロードアベレージは、1,5,15分の平均値です。 w でも代用可能。

$ uptime
11:44:16 up 49 days,  5:41,  1 user,  load average: 0.00, 0.00, 0.00
$ w
11:44:17 up 49 days,  5:41,  1 user,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
user     pts/0    www5339u.sakura. Tue09    0.00s  0.56s  0.09s w

SELinux

SELinux(Security-Enhanced Linux)の設定を行います。rootに権限が集中することを防ぐシステムの構築を提供します [158]

[158]wikipediaを参考にしました。ちゃんと知りたい方は調べてください(続きは英語で)
.. index:: chcon

chcon

選択されたファイルのSELinuxセキュリティーコンテキストを変更します。

オプションは下記の通り

--dereference シンボリックリンクに影響せず、シンボリックリンク先のファイルに影響します。デフォルトの動作です。
-h シンボリックリンクのみに影響します
--reference=rfile
 rfileと同じ設定になります
-R 再帰的な感じで動作します
-v すべてのファイルについて調べて表示します
-u user セキュリティーコンテキストをユーザ userに設定します
-r role セキュリティーコンテキストをロール roleに設定します
-t type セキュリティーコンテキストをタイプ typeに設定します
-l range セキュリティーコンテキストをレンジ rangeに設定します
.. index:: runcon

runcon

特殊なSELinuxのコンテキスト上でコマンドを実行します。オプションです。

runcon context command [args]
runcon [options] command [args]
-c 変更する前にプロセス変更コンテキストを計算する [159]
-u,-r,-t,-l
chcon のオプションと同じ
[159]Compute process transition context before modifying の訳。ムズイ

変更コマンド

いろいろ変更しまっせ。

.. index:: chroot

chroot

特定のルートディレクトリでコマンドを実行します。スーパーユーザでのみ実行できます [160] 。何がうれしいの?というと、本来ならば、/ディレクトリからのツリー構造になっているものを、任意のディレクトリ(/tmp/chroot/など)を/と再定義したツリー構造に変更することができます。つまり、本来の/は見えなくなります。ソフトウエアのテストなどを行うときに使います [161]

[160]例外あり

実行はこんな感じ。

chroot option newroot [ command [args] ... ]
chroot option
[161]原文に書いてある例を実行してみたんですがうまく動かず。本来だったら/直下の必要なファイルを任意のディレクトリにコピーして実行するものらしい
.. index:: env

env

環境変数を表示したり、一時的に環境を変数を変更してコマンドを実行します。 env 単体で実行すると、設定されている環境変数が表示されます。 一時的に環境変数を変更するときの例。/tmp/binというディレクトリにHOGEと出力される実行可能なhogeファイルをおいておきます。

env PATH="$PATH:/tmp/bin" hoge
HOGE

オプションは下記の通りです

-O,--null
出力時に改行しません [162]
[162]新しめのバージョンに入っているオプションらしい
-u name
nameという環境変数を削除します
-,-i,--ignore-environment
環境変数をすっからかんにして実行します。さっきのコマンドをアレンジしてみましょう。
env # まずは実行して様子見
env - PATH="$PATH:/tmp/bin" env

なんとなく実行結果はつかめましたか?

.. index:: nice

nice

いいね!コマンドです [163] 。nicenessを変更してプログラムを実行します。nicenessって何?いい質問ですね [164] 。nicenessは、システムで実行されるプロセスがいくつかあってその中でどれくらい有利に実行されるかを決める値です [165]

[163]正しくはlike
[164]いいね!(言いたいだけだろ!!
[165]厳密には違うけど適当な説明ならこれでおっけー!(こらこら

単体で実行すると、現在のnice値が表示されます。-20 (優先度高) から19 (優先度低) までの値をとります。そしてnicenessはスケジュールの優先度と混同してはいけません。アプリケーションを実行する順序を決めます。nicenessはスケジューラーに単に忠告するだけで、無視することもあります(そして原文ではhistrical practiceに脱線)。

実行例から。数値を与えればそれだけnice値が下がります。

$ nice
0 # current nice
$ nice nice
10
$ nice -n 19 nice
19
$ nice --10 nice
nice: cannnot set niceness: Permission denied

niceをつけてコマンドを実行すると、nice値が10になります。 -n をつけると数値を指定できます。 - のあとに数値をつけると -n 数値 と同じ効果です。 --10 はマイナス値にしようとしています。マイナス値をつけることはnicenessをあげることになります。nicenessをマイナス値にするためには、root権限が必要です。

$ sudo nice -n -20 nice
-20

コマンドまとめてniceする場合はこんな感じです [166]

[166]http://unix.stackexchange.com/questions/22146/set-niceness-to-piped-command
$ nice -n 15 sh -c "command | command | command"

ちなみに、 renice コマンドで実行中のプロセスのnice値を変更することができます。多分いける。

.. index:: nohup

nohup

ログアウトしても実行したコマンドを実行し続けることができるコマンドです。

$ nohup yes asumisu &
$ logout

これで、いつでもイエッスアスミスし放題ですね [167] 。実際に実行するときは注意してくださいね。

[167]ディスクを食い尽くしてプロセスが落ちるところまでがオチです(ドヤァ

hungupシグナルを無視して、引数のコマンドを実行します。ログアウトしたあとでも引き続き実行されます。 標準入力がターミナルのとき、/dev/nullからリダイレクトされます。ターミナルのセッションはコマンドによって使われるターミナルと誤って見なさないようにするためです [168]。これはGNU拡張で、GNUでないシステムでは、 nohup command [arg] ... </dev/null として下さい。

[168]これを書いている筆者もよくわかってない

標準出力がターミナルのとき、コマンドの標準出力はnohup.outファイルに追記されます [169]

[169]そのファイルに書けない場合は、$HOME/hohup.outに書き、そこもだめだった場合はコマンドは実行されません。nohup.outファイルは、コマンドを実行しているユーザだけが書き込みができ、且つ読み込みができる権限で作られます。umaskを無視します

標準エラーがターミナルのとき、標準出力に出ます。標準出力が閉じられているときは、上記のnohup.outファイルに追記されます。

例を見ましょう。

$ nohup make > make.log

ちゃんとバックグラウンドで実行するには、「イエッス、アスミス」で出てきたように、コマンドの最後に & を置きましょう。もし、 nice を使いたいときは、 nohup nice command としてください。

.. index:: stdbuf

stdbuf

Coreutils 7.5 (2009-08-20) から追加されたコマンドです。説明が難しいので、原文直訳気味です。

i/oストリームバッファリングを変更してコマンドを実行します。stdbufは、プログラムに関連づけられた3つの標準I/Oストリーム(標準出力、標準入力、標準エラー出力)のバッファリング動作を1つに変更できます。オプションはもちろん3つ、

-i mode, --input=mode
 標準入力ストリーミングバッファリングを調整します
-o mode, --output=mode
 標準出力ストリーミングバッファリングを調整します
-e mode, --error=mode
 標準エラーストリーミングバッファリングを調整します

modeに指定する文字は下記です

L
ストリームを行単位でバッファします。このモードでは、新しい行が出力されるか、入力がターミナルデバイスに接続されたストリームから読まれるまで結合します。このオプションは標準入力では使えません。
0
大文字のoではなく、ゼロです。選択されたストリームのバッファリングを無効にします。このモードでは、データはただちに出力され、要求されたデータの分だけが入力から読み込まれます。入力と出力のための機能の違いに注意してください。入力のバッファリングを無効にすると、応答性やストリーム入力機能のブロッキング動作に影響を与えません。基本的には、要求されたよりも少ないデータを読み取る場合でも、たとえば関数freadの場合はまだ、EOFかエラーになるまでブロックします [170]
size
完全バッファモードにおいて、バッファのサイズを明確にします。サイズは整数のあとにKB(1000 KiloBytes)とかK(1024KibiBytes)をつけることができます
tail -f access.log | stdbuf -oL cut -d ' ' -f1 | uniq

このコマンドでは access.log の一意なエントリがあると直ちに出力されます [171]

command | stdbuf -oL gawk \
 '{print strftime("[%a %b %e %H:%M:%S %Z %Y] "), $0; }'

コマンドの標準出力にタイムスタンプを追加する例です [172] 。このコマンドの具体的な活用例はあまりないので、エントリを上げるチャンスですよ!

[170]google翻訳を借りました。以前見た時よりも翻訳が自然になっていて驚き。そして翻訳された日本語の文章の意味はイマイチ把握できず
[171]日本語マニュアルからお借りしました
[172]http://qiita.com/yyamamot/items/60a0a007b0016da61b32
.. index:: timeout

timeout

タイムリミットを設定してコマンドを実行します。Coreutils 7.0 (2008-10-05) より加入。CentOS 5系だと入っていないかも。

timeout [option] duration command [arg] ...

オプションは下記の通り

--preserve-status
 タイムアウトを示す具体的な終了ステータスを返します。どのくらいかかるかわからないコマンドを実行するときに便利 [173]
--foreground 正常フォアグラウンドTTYを使用できるように、独立したバックグラウンドプログラムループを作成しません。これは、コマンドが2つの状況で、対話型シェルから直接起動していないコマンドがタイムアウトをサポートするために必要とされます。2つの状況とは、 1. commandがインタラクティブで、例えば端末から読み取る必要がある場合 2. 端末からコマンドを直接送信したい場合、たとえばCtrl-Cなど
-k duration, --kill-after=duration
 監視コマンドは、指定した期間のあとに、KILLシグナルを送ることによってkillされていることを確認します。選択された信号が致命的でないと証明された場合、このオプションを指定しない場合、コマンドをkillすることはありません
-s signal, --signal=signal
 デフォルトであるTERMシグナルではなく、タイムアウトの時にsignalをコマンドに送ります。signalはHUPや数値で指定します。単に数値の場合は秒です

期間に関しては、小数の後に、s(秒、デフォルト)、分であるm、時間h、日dをとることができます。期間が0の場合、タイムアウトになりません。実質のタイムアウトの期間はシステムの状態に依存します。特に注意しないといけないのは、1秒以内のタイムアウトです。

「イエッス、アスミス」に細工します [175]

$ timeout 5 nohup yes asumisu &

5秒後に実行が終わるので、ディスクにも安心。

[173]原文にはスペルミスがあるので訳すときは注意。と、書いていたのですが、この本を読んでいただいた方から、Coreutilsにバグレポートを送っていただきました。最新のCoreutilsのマニュアルでは修正済みです。やりとりはこんな感じでした(https://twitter.com/okano_t/status/507278269524082689)。@okano_tさん、ありがとうございました。バグレポートってこんなかんじで送るのかーと知見を得ました
[174]コマンドが2つの状況ってなんでしょうね。バックグラウンドとフォアグラウンドのこと?おしえてエロい人!
[175]この言い方が適切かどうかは不明

プロセスコントロール

この章にはkillしかありません。

.. index:: kill

kill

非実在の妖精さん(プロセス)にお菓子(シグナル)を与えます [177] 。お菓子(シグナル)にもいろいろあって、それを食べた妖精さん(プロセス)は、消えてみたり、いっぺん寝て起きてみたり、「どうされましたか?」 [176] などと言ってみたりします。お菓子によってどのような行動をするかは、妖精さんごとに定義されています。

killコマンドのデフォルトでは、TERMというお菓子を妖精さんに与えます [180] 。 お菓子(シグナル)には、番号や名前がついています。HUP(番号だと1) [178] 、KILL(番号だと9) [179] などです。詳細は、Coreutilsのマニュアル、2.5 Signal specificationsに載っています [181] 。なお、ちゃんと言うことをきいてくれる(アクセス権限のある)妖精さんにしか効果ありませんのでご注意を。

[176]null signalのイメージ(多分ちょっと違う)
[177]ググってみるとプロセスを強制終了するコマンドという説明を見かけます。これは、正確ではありません
[178]ログをローテートさせるときに使います。apacheのlogrogateであれば
[179]プロセスを終了させるときに使います。通常「殺す」って言います。なお、このシグナルは、受け取り拒否または無視できません
[180]システムコールの世界にようこそ
[181]あのシグナルなんだっけ?というときは、 $ man 7 signal してください

よくあるコマンドを示します。「-9」というお菓子を、妖精さんの番号「12345」(プロセスID/PID)に与えます。2つのコマンドとも同じ意味です。

$ kill -9 12345
$ kill -KILL 12345

妖精さんの番号が正の数の時、0の時、-1の時、-1より小さい時の説明があります。気になる人は自分で調べてみてください。なお、 killall というコマンドがあります。これは、引数にプロセス名を取ります。rootで単に killall を実行すると、すべてのプロセスが終了します(UNIX System Vバージョンの場合) [182]

[182]このへんはwikipediaあたりを参照しました

遅延

Delayingです。

.. index:: sleep

sleep

指定された時間だけ休憩します。アラームとか実行するといいんじゃないでしょうか。

$ sleep 1d 1h 1m 1s && echo $'\a'

1日+1時間+1分+1秒後にビープ音を鳴らします [183] 。もちろん、このコマンドを実行するマシンは足元にないとだめですよ [184] [185]

[183]筆者の部屋に転がってたfreeBSDの入った実機で echo $'a' を実行してみたら「ピッ」って鳴った。手元のMacBookAirのターミナルでやってみても鳴った
[184]クラウド上のサーバがピーピーなっちゃいますよ(ホントかなぁ
[185]以前契約していたvalue-serverで大量に実行してみたけど怒られなかったし、いいんじゃないでしょうか。そもそも一般ユーザで鳴るのかね?まあいいか

数値操作

.. index:: factor

factor

「せんせい!そいんすうぶんかいがしたいです」「よろしい、ならば戦争(ry」「おいやめろ!!」ということがないように、素因数分解ができるコマンドがあります。

$ factor 60
60: 2 2 3 5

原文だと唐突に、メルセンヌ素数をもとに実行例が出てきます。曰く、8番目と9番目のメルセンヌ素数 [186] を計算するときには、Athlonの2.2GHzのCPUで30ミリ秒くらいかかります [187]  、とあります。

M8=$(echo 2^31-1|bc)
M9=$(echo 2^61-1|bc)
n=$(echo "$M8 * $M9" | bc)
/usr/bin/time -f %U factor $n
4951760154835678088235319297: 2147483647 2305843009213693951
0.03

さらに読んでいきましょう。8番目のフェルマー数 [188] (2^256+1)は20秒くらいかかります [189]

[186]2^n-1(nは自然数)の形の自然数且つ素数。ちなみに48番目が発見された日は、2013年1月、って最近じゃないか。物好きな方はGIMPSでググると吉
[187]さくらのサーバでやってみたら桁数多すぎで怒られました。velue-serverでやってみたら、0.02でした
[188]フェルマー数とは、2^2^n+1(nは自然数)
[189]この文章書かれたのいつなんでしょうね?

大きい数になると一般的に求めるのが難しくなります。比較的小さい数字を求めるときに、ポラード・ロー因数分解法が使われます。でかい数で且つ素因数がおっきい数を求めるときは、もっとほかの方法をとった方がよさげです。

GNU MP [190] を使わずにビルドされたfactorコマンドは、single-precision算術が有効になります。その算術方法は、小さい数字を計算することが得意で、2^64以上の数字はサポートしていません。158909489063877810457や222087527029934481871の素因数分解をするときにループに陥りましたが、coreutils 8.20でバグってて、8.27 で修正されました。普通こんなことしないと思いますが念のため。

[190]GMPといって、多倍長演算ライブラリのことです。http://gmplib.org を参照

「せんせい!1000までの素数が知りたいです」「よろしい、ならば戦争(ry」と、なってしまったら?ここで答えを書いてしまうと面白くないので、あとがきに載せました。

.. index:: numfmt

numfmt

Coreutils 8.21 (2013-02-14) から使える比較的新しいコマンドです [191] 。 例えば、4Gを4,000,000に変換してくれます。例をいくつか拾ってみましょう。詳しいことはマニュアルを読みましょう。

[191]ついでに、4章(fmtとかがあるところ)からこの章に説明が移動してました
$ numfmt --from=auto 1Mi
1048576

$ numfmt --to=si 500000
500K

# Third field (file size) will be shown in SI representation
$ ls -log | numfmt --field 3 --header --to=si | head -n4
-rw-r--r--  1     94K Aug 23  2011 ABOUT-NLS
-rw-r--r--  1    3.7K Jan  7 16:15 AUTHORS
-rw-r--r--  1     36K Jun  1  2011 COPYING
-rw-r--r--  1       0 Jan  7 15:15 ChangeLog

$ LC_ALL=en_US.utf8 numfmt --from=iec --grouping 2G
2,147,483,648
.. index:: seq

seq

連続した数字を表示します。使う頻度はそこそこ多いかもしれないです [192] 。実行例はこんな感じ。

[192]bashのカッコ展開で代用することも多いかも。{1..100}とか
$ seq 3
1
2
3
$ seq -w 7 10
07
08
09
10
$ seq 1 2 5
1
3
5
$ seq -w 10 -2 2
10
08
06
04
02
$ seq -s "," 10 -2 2
10,8,6,4,2
$ seq -s + 1 100 | bc
5050

オプションに関しては察してください。あとは-fオプションでprintfと同じようなフォーマットが使えるモードがあります。あとは非常に大きい数字の場合、5e+06といったような表現になるときがあります。そんなときは、-fを使ってフォーマットを指定して解決。

$ seq 20140401 20140410
2.01404e+07
2.01404e+07
2.01404e+07
2.01404e+07
2.01404e+07
2.01404e+07
2.01404e+07
2.01404e+07
2.01404e+07
2.01404e+07
$ seq -f %1.f 20140401 20140410
20140401
20140402
20140403
20140404
20140405
20140406
20140407
20140408
20140409
20140410

seq 1 0 10 ってコマンドを実行すると無限ループしていました。インクリメントが0ですね。無限ループ回避として、coreutils 8.26からエラーになります。見逃されていたというかなんというか。

答え合わせ

文中で出てきた問題の解答例と解説です。脚注の[練習問題]は、自習ということでひとつ。

date

dateコマンドで出てきた問題の解答です。前月の最終日の日にちを表示するすワンライナーでしたね。こちらです。

date -d $(date +%Y%m01)'-1day' +%Y%m%d

計算しててずるい感じしますがこうするしかなかったです。もっと短くかける方、いますぐ筆者までリプライください。

factor

factor で出てきた、1000までの素数を表示するワンライナーです。某所でバズったのでご存知の方がいるかもしれません [193] 。 解答例はこちらです。

[193]元ネタはこのへんです http://oki2a24.com/2014/03/03/how-to-print-prime-number-to-10000-with-shell/ https://twitter.com/usptomo/status/479858878310383616
$ seq 1 1000 | factor | awk 'NF==2{print $2}'

解説すると、 seq で1から1000までの数値を出して factor に食わせます。

seq 1 1000 | factor | tail
991: 991
992: 2 2 2 2 2 31
993: 3 331
994: 2 7 71
995: 5 199
996: 2 2 3 83
997: 997
998: 2 499
999: 3 3 3 37
1000: 2 2 2 5 5 5

次に awk を使ってフィールドの数が2つのものだけを抽出します。フィールドというのは、例えば「999: 3 3 3 37」でいうとことの「999:」「3」「37」にあたる部分です。この場合、フィールド数は5です。 フィールドが2のものは「991: 991」とか「997: 997」とかで、素数になっていますね。あとは、2番目の文字を出力( print $2 )すれば終わりです。

さて、sed派の皆さん、お待たせしました。 sed で処理をするならこちらです [194] 。解説をすると、

seq 1 1000 | factor | sed -n '/: [^ ]*$/{s/.*: //;p}'

オプションの解説です [194]

[194](1, 2) sed方式は @richmikan 氏に解説含め教えていただきました
-nオプション
pコマンド(print)が指定されない限り勝手に表示しない
/: [^ ]*$/
AWKでいうパターンに相当するもので、": "の後ろにスペース無し(つまり素数行)だけ反応する
{~}
上記のパターンにマッチしたら括弧の中のコマンドを実行
s/.*: //
1列目の文字列を消す
p
その結果を表示する