Unixコマンド生活実践
Unixで生活する上の実践的な知識を説明します
これは何か
- Unixで生活する上の実践的な知識を説明します。
- 普段使うコマンドを説明します。
- シェルはbashを前提にしています。
ディレクトリ移動
.と..は常識なので省略
pwd ...カレントディレクトリの表示(pwd:print working directory) cd ...ホームディレクトリに戻る cd ~ ...同上 cd - ...直前にいたディレクトリに戻る
pushdとpopdは一時使っていましたが、個人的には最近使わなくなりました(試して気に入れば使ってください)。
ファイル操作
空ファイルを作る時に使う touch filename cp /dev/null filename ファイルの情報を表示 stat filename
ディレクトリ操作
lsの使うオプション ...-l,-a,-F,-i
# ディレクトリをすべて消す場合(先頭の\は後述) \rm -rf ディレクトリ名 # 全部コピー cp -ar srcdir destdir ...-aはGNU lsのオプション # cp -aがどこまで信用できるか不明、あるいはGNU lsがない時に、使うテクニック tar cf - srcdir | (cd /destdir; tar xf -)
ファイル操作(リンク)
ハードリンク vs. シンボリックリンク
ln #ハードリンク ...異なるファイル名で同一のi-nodeを共有(ls -iで確認可能) ln -s #シンボリックリンク ...ポインタ
注意点
- ハードリンクは対称(ln a bでもファイルaとbに主従関係はない)
- i-nodeはデバイス(dfで見えるディスクデバイス)で一意なので、デバイスを越えてハードリンクは作れない
- シンボリックリンクは指定したファイルパスを持っているだけ。相対パスで指定すれば相対パスとしてリンクするので注意。
ファイル操作(アーカイブ)
なんでもtar。GNU tarだとコマンドラインオプションでそのままgzipやbzip化できます。
tar zcf srcdir.tar.gz ./srcdir #相対ディレクトリ指定の方が安全 tar ztf srcdir.tar.gz #中身を見る tar zxf srcdir.tar.gz #展開 # zをjに変えるとbzip tar jcf srcdir.tar.bz ./srcdir #たいていgzipより圧縮率が良いようです(でも送り先の相手がbunzipできないかも)
GNU tarがない時、パイプを使います
tar cf - ./srcdir | gzip - > srcdir.tar.gz gunzip -c srcdir.tar.gz |tar xf -
Unixのディレクトリ構成
歴史的なディレクトリ
/etc #この下のファイルをどれだけ知っているかでUnixマニアぶりが分かります(/etcを見てバージョンまで含めてOSが分かれば通) /sbin # 歴史的にはstatic linkした実行ファイルを置くディレクトリでしたが、今や管理者用コマンドを置くディレクトリ /dev # 昔はmknodでデバイスファイルを手動で作ることもありましたが、今やコマンドラインから使うのは/dev/nullと/dev/zeroぐらい /usr/local #パッケージ管理全盛の今、手動インストールしたプログラムの置き場 /var #/varはログファイルなどでディスクフルになりやすいので、/(ルート)とパーティションを分ける、という流儀もあります /opt #SVR4(Solarisなど)派の人が手動インストールしたプログラムを置く場所
/lost+found #fsckで行き場を失ったファイル(要はディレクトリ破壊)が移動させられるディレクトリ(ディスクデバイスごとにひとつ)
新興ディレクトリ
/root #rootユーザのホームディレクトリ /proc #Solaris発祥、Linux追随。かなり便利。とりあえずファイルの中を見るべし
環境変数に注意
はまりがち(自分のところと他の人のところで動きが違う。suで別ユーザ権限にしたら動きが違う。など)
env #現在の環境変数の一覧 echo $PATH #特定の環境変数の値を表示 su - #suした対象ユーザのログイン時と同じ環境変数になるので、たいてい、この方が安全(今時はsudoの方が人気) su - -c コマンド #suしてコマンド実行する場合
- ちなみに環境変数とは、子プロセスに引き継がれる変数のこと
- 環境変数にまつわるFAQ (sh ~/.bash_profileしても環境変数が反映されない => 理由を答えられること)
- 環境変数PATHにカレントディレクトリを含めると素人判定されるのでやってはいけません
便利な環境変数
export IGNOREEOF=-1 export HISTSIZE=65535 export HISTFILESIZE=65535 export HISTCONTROL=ignoredups
aliasの活用
他の人のaliasを盗むべし
# 伝統のalias alias ls='ls -aF' alias rm='rm -i' alias mv='mv -i' alias cp='cp -i' alias ll='ls -l'
-iでうっかりミスを防げますが、鬱陶しい時もあるので、回避したい場合、rmのようにバックスラッシュをつけるのが便利(/bin/rmでもOK)
# aliasの確認 type ls
manとinfo
とりあえずman。infoはGNU発祥です。
man -k keyword #キーワード検索(あまり使えない...) man 2 write #セクションを指定。セクションの意味はman man(1,2,3は常識)
readline(コマンドラインの編集)とhistory
他の人の.inputrcを盗むべし
~/.inputrc "\C-n":history-search-forward "\C-p":history-search-backward set show-all-if-ambiguous on
!! #直前のコマンド !ma #maで始まる直前のコマンド
コマンドプロンプトのカスタマイズ
- 環境変数PS1で色々遊べます。
- 好みに応じて
- 個人的に昔はカレントディレクトリを表示する流儀でしたが、プロンプトの長さが変化するのが嫌で最近はしていません
ファイルの検索
locate #ファイル名のパターンで検索。意外に使える(インデックス構築処理があるので、作った直後のファイルは検索対象外) find #奇天烈コマンドの王様
find
find . -name foo find . -name foo ! -type d #and条件 find . -name foo -o ! -type d #or条件 find . -name foo -exec cp /tmp/foo {} \; #{}が見つかったファイルパス名に置き換わってコマンド実行 \; でコマンド終端 find . -type f | xargs tail #xargsは標準入力をコマンドラインオプションに分配するコマンド
find and for
少し複雑な場合、-execオプションよりforに渡す方が簡易に書けます。
for f in `find . -type f` do sed 's/foo/bar/g' $f > $f.bak mv $f.bak $f done
プロセスkill
kill プロセスID killall プロセス
Unixのプロセスを殺す方法はシグナル(一覧はman 7 signal)を送ることで実現します。なるべく穏便(=正常な終了処理をする)な死に方をするシグナルから試します。
SIGHUP 1 #伝統的にサーバ系ソフトは設定ファイルの再読み込み処理に割り当てていることが多いです SIGINT 2 SIGTERM 15 SIGKILL 9 #これは最後に試す
screen
誰かの.screenrcをもらうこと
ページャ
cat #本来はファイル連結用コマンド(splitで分割してcatで連結) more less view #実体はviのハードリンク(read-only)。argv[0]でモード切り替えをする古典的テクニック lv tac #catの逆向き
作業ログ
script /tmp/record
すべてのシェル上のやりとりがファイルに記録できます。
command | tee /tmp/record
commandの標準出力を画面とファイルの両方に出力できます。
ログを見る時の基本
ls -lrt #最後に更新されたログファイルを見つけたい時 tail -f logfile #基本テクニック
tail -fでも画面からあふれる時の端末制御
- ctrl-sで停止、ctrl-qで再開
grep
# よく使うオプション grep -r #ディレクトリを再帰的にgrep (GNU grep拡張) grep -i #大文字小文字無視 grep -An #nは数値。マッチした行の後(after)も表示 grep -Bn #nは数値。マッチした行の前(before)も表示 grep -c #マッチした行の行数(count) grep -v #マッチしない行を表示
sed
ちょっとした文字列置換には便利
command | sed 's/old/new/g' | ...
- oldは正規表現
- /が多い文字列を置換する場合、別の任意の文字(barや!がよく使われます)を区切り文字に使えます。
command | sed 's|old|new|g' | ...
sed(2)
一部を切り出す処理も、典型的な場合は定石を使って条件反射的に書けます。
例えばdovecotのimapのログから名前の部分を取り出すsed
dovecot: Jul 24 17:45:57 Info: imap-login: Login: user=<hana>, method=PLAIN, rip=1.2.3.4, lip=4.3.2.1 grep imap-login dovecot.log | sed 's/.*user=<\([^>]*\)>.*/\1/g'
定石(sedのs/A/B/gのAの部分を分解)
.* 適当にexactマッチしそうな文字列 ...上の例では user=< \( ...グルーピングのためのカッコ(要エスケープ) [^X] ...Xの部分は取り出したいパターンの終端文字。上の例では > *\)X ...X以外の文字の繰り返しとグルーピングのためのカッコ .*
awk
特定のカラムを抜き出す時には便利です。cutコマンドは意外に使いづらいので、awkの方が楽です
command | awk '{print $2,$3}' | ...
カンマ区切り(CSV)の場合、区切り文字をデフォルトの空白文字(スペースやタブ)から変更します。
command | awk -F, '{print $2,$3}' | ...
マッチした行に対してカラムの値で演算する、ぐらいはawkが楽です(これ以上複雑なことをするならperlでいいかも)。
command | awk '/マッチするパターン/{print $2,$3,$2+$3}' | ...
join
まれに使うjoin(RDBの文脈で使うjoin処理のこと)。一応、awk,join,catでSQLのselect,join,unionらしきことができます。
0 foo 1 bar 2 baz と 0 FOO 1 BAR 3 BAZ から 0 foo FOO 1 bar BAR を得られる(join -1 1 -2 1 input1 input2)
testコマンド
testコマンドは別名で [ コマンドでも使えます(普通、シェルの組み込みコマンド)。
ファイルのチェックなどに使うことがあります。
[ -e /tmp/foo ] || touch /tmp/foo #ファイルが無ければ作る [ -e /tmp/foo ] && /bin/rm /tmp/foo #ファイルがあれば消す
man test を参照
リダイレクト
読み方
- 0:標準入力、1:標準出力、2:標準エラー出力 (0,1,2などはファイルディスクリプタ)
- X>&Yは、「ディスクリプタXをディスクリプタYの複製として(=Yが参照する先を指すようにXを)リオープンする」と読みます。
- リダイレクト処理は左から読みます(注:パイプがある場合、パイプを先に解釈)
- >fileは1>fileの省略。<fileは0<fileの省略。
command >file 2>&1 #1をfileでreopen。2をfileでreopen command 2>&1 >file #2を端末(画面)でreopen。1をfileでreopen
リダイレクトとパイプ
読み方
- リダイレクト処理は左から読みます(注:パイプがある場合、パイプを先に解釈)
command 2>&1 | command2 #2をパイプでreopen(1も2もパイプへ) command >file 2>&1 | command2 #1をfileでreopen。2をfileでreopen command 2>&1 >file | command2 #2をパイプでreopen。1をfileでreopen
- パイプの実験先として、あまり害がないかつ入力が空だとすぐ分かるので、wcコマンドをよく使います
- 出力を捨てたい時はリダイレクト先に /dev/null を使います
グルーピング
(command; command) #子プロセスで実行。スペースはあってもなくても可。最後の;はあっても可 { command; command; } #カレントプロセス。前後のスペースと最後の;は必要。
ネットワーク管理
# よく使うオプション netstat -anpt #ソケットの状態を表示(grepでフィルタ) netstat -rn #ルーティングテーブルの状態を表示 ifconifg -a #ネットワークインターフェースの状態を表示 arp -an #ARP表の表示 dig -t MX @ns.ariel-networks.com ariel-networks.com #DNSの動作確認