holly's wiki - コンソールねた
仕事で使えそうな(使ってる)コンソール作業ねた。あまりたいしたことはしてないけど、まあまあ便利な使い方をつらつらと書いていく。

shell変数

結構奥が深いのでshell変数ねたにまとめ

openssl

それなりに多いのでopensslねたにまとめ

perl

それなりに多いのでperlねたにまとめ

network関係

なんとなくnetworkねたにまとめ

shortcut

ショートカットというかキーボード操作でいろいろ

カーソル位置

カーソルだけ移動したい場合
入力説明
Ctrl+A行頭に移動
Ctrl+E行末に移動
Ctrl+B1文字左に移動
Ctrl+F1文字右に移動
ESC+B1単語左に移動
ESC+F1単語右に移動
Ctrl+D, Cltl+H一文字削除

インクリメンタルサーチ

Ctrl+r。historyで探さなくても便利。zshだと
bck-i-search:
とでる

突然キー入力できなくなる問題

Ctrl+sキー入力できなくなったように見える操作
Ctrl+qキー入力できなくなった状態を解除する操作
この機能自体いらないという場合は.bashrcなどに
stty stop undef
とすればよい

仮想コンソール

最近はtmuxとかあるから使うことそんなにないけどAlt+F1 - F6でそれぞれの画面を切り替えることが可能。gpmサービスが動作していれば,仮想コンソール間でコピー&ペーストも可能らしい。不要であれば/etc/inittabに
1:12345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
と記述されているので、不要なのをコメントアウトなりすれば多少メモリの節約になる。

man section

忘れがちなので
  1. だれもが実行できるユーザコマンド
  2. システムコール、つまり、カーネルが提供する関数
  3. サブルーチン、つまり、ライブラリ関数
  4. デバイス、つまり、/dev ディレクトリのスペシャルファイル
  5. ファイルフォーマットの説明、例 /etc/passwd
  6. ゲーム。明らかにいらん
  7. その他 例: マクロパッケージや取り決め的な文書
  8. システム管理者だけが実行できるシステム管理用のツール
  9. Linux 独自のカーネルルーチン用のドキュメンテーション

その他(よくわからん)
n. 新しいドキュメンテーション: よりふさわしい場所に移動されるだろう
o. 古いドキュメンテーション 猶予期間として保存されているもの
l. 独自のシステムについてのローカルなドキュメンテーション

set

shellscriptを作るときとか。古い記事だけどまとまっているのがあった。http://itpro.nikkeibp.co.jp/article/COLUMN/2006022...

実行内容を表示

スクリプト内で
set -x 
find /path/to/dir -type f 
などとすると実行結果に
+ find /path/to/dir -type f
として出力される

実行コマンドエラーで処理をとめる

set -e

rmdir /path/to/dir
echo /path/to/dir delete
この場合だとrmdirで失敗すると次の処理には進まない

expr

使い方はいろいろあるけど

計算

足し算
expr 1 + 1
2
引き算
expr 1 - 1
0
掛け算
expr 1 * 1
とするとsyntax errorとなるので
expr 1 \* 1
1
とする
割り算
expr 1 / 1
1
剰余演算
expr 1 % 1
0

文字列演算

byte数
str="nirvana"
expr length $str
7
指定文字の位置
str="nirvana"
expr index $str "a"
5
substr
str="nirvana"
expr substr $str 1 3
nirvana
正規表現
正規表現の先頭に暗黙のうちに"^"(行頭)が付加されることに注意。マッチした部分の文字数が返される。\(\)で囲んでいる場合は副表現でマッチした文字列が返される
expr match "i love nirvana" ".*love"  
6
当然マッチした場合はNULLが返されて、終了コードは0以外となる

find

よく使うけど、結構奥が深い。どっかに書いてないと忘れそうなのだけ記載

一部を検索除外

pruneを使う。最後は必ず-o -printをつけないと期待通りの結果は得られない
nameで除外
find . \( -name .pythonbrew -prune -o -name .virtualenvs -prune \) -o -print
pathで除外
find /path/to \( -path '/path/to/.pythonbrew' -prune -o -path '/path/to/.virtualenvs' -prune \) -o  -print

find + xargs

結構よく使ったり

コマンドに渡す引数が多すぎる

例えばfooディレクトリ以下の拡張子が.tmpのファイルを削除したい場合、
find /path/to/foo -type f -name '*.tmp' -exec rm {} \;
などとするが、この場合だと *.tmp のファイルの数だけ rm が実行され、時間がかかる。 (*.tmpが10000個あるとrmが10000回実行されることになる)また、
rm /path/to/foo/*.tmp
単純にこれでもよいが、*.tmpのファイル数があまりにも多すぎる場合、
argument list too long
とエラーになるその場合は
getconf ARG_MAX
freebsdなら
sysctl -A kern.argmax
で調べられる。で上記の2例のような場合にxargsを使うとよい。findの例だと
find /path/to/foo -type f -name '*.tmp' | xargs -n100 rm
この場合だとxargsはrmの引数を100個受け取ってから実行するようになるので、rmの回数が極端に減る(実行速度も大幅に速くなるらしい)。rmの例の場合のように引数の制限に引っかかることもない。オプション -n(もしくは--max-args=max-args)は引数に受け取る数値。-n1とか指定がない場合は引数は1個ずつとなる。なので
find /path/to/foo -type f -name '*.tmp' | xargs -n1 rm
は一番はじめに例にだしたfindの実行例と同じになる。その他xargsを使って並列処理を行ったりすることができたりする。ちなみにxargsした時にどんなコマンドを実行したか見たいときは -t をつければ確認することができる。
元ねたはhttp://d.hatena.ne.jp/lurker/20070117/1169039924

rmで削除できないファイルを削除する

ls -lの結果で
-rw-r--r-- 1 root root     2 2009-01-01 19:15 ??????
こんなことになってる場合は当然
rm ??????
などとしても削除できない。そんなときはinodeを調べて削除する。まずinodeを調べる
ls -i
82170 ??????
などとするとinodeがわかるので、あとはfindとxargsを組み合わせて削除する
find -inum 82170 -print0 | xargs -O rm -f
とすると削除できる。findの出力オプションはかならず-print0をつけて、xargsで受ける時に-Oオプションをつけること。

パイプで渡された結果を「{}」で展開

xargsの-iオプションを指定する
# どっかのぱくりです。いい例が思いつかなかった
find . -type f -print0 | xargs -0 -i mv '{}' /var/tmp/
findでマッチしたファイルが{}の部分で展開され、/var/tmp以下に移動される。って意味になる

その他

めんどくさいので http://codezine.jp/article/detail/3279 参照

sort + uniq

これも結構よく使ったり

重複する行をまとめる

cat sample.txt
kurt
foo
bar
foo
hoge
kurt
hage
bar
bar
holly
kurt
upo
kurt
こんなファイルがあったとして
sort sample.txt | uniq
bar
foo
hage
hoge
holly
kurt
upo
としてsortしてuniqを使用すると重複した文字列は一度しか表示されない。もしくは
sort -u sample.txt
としても同じ結果となる

ユニークな行だけ表示

uをつけるとよい
sort sample.txt | uniq -u
hage
hoge
holly
upo

重複行だけ表示

dをつけるとよい
sort sample.txt | uniq -d
bar
foo
kurt

それぞれの文字列の出現回数の多い順に表示

sortした状態にしてuniqを行う。この時に-cをつけると出現回数が表示される。この状態でさらにsort -nで先頭の数値順で並び替えるが、このままだと昇順になるので、降順にするには-rをつける。
と長ったらしい説明になったが
sort sample.txt  | uniq -c | sort -nr
      4 kurt
      3 bar
      2 foo
      1 upo
      1 holly
      1 hoge
      1 hage
とすると思い通りの結果を得ることができる

指定フィールドでsortする

cat list.txt
1       holly   30
2       oton    58
3       okan    60
4       onii    31
5       tora    5
6       momo    3
ID,名前,年齢ごとのデータを記述したファイルがあるとして、年齢で降順sortを行いたい場合は-kでsortを行うフィールドを指定する
sort -nrk 3 list.txt
3       okan    60
2       oton    58
4       onii    31
1       holly   30
5       tora    5
6       momo    3
となる

ssh

初めてのサーバに接続する時に警告がでるのがうっとうしい

よくyes/noを聞いてくるので無視したい。
The authenticity of host 'remote server (xxx.xxx.xx.xx)' can't be established.
RSA key fingerprint is 77:69:25:f0:96:02:41:0b:bf:c9:88:fb:03:9b:55:44.
Are you sure you want to continue connecting (yes/no)?
とこういうのが出てくるのだけど、プログラム的にssh接続などをしているとこれが出るとプログラムがそこで止まってしまったりするので何とかしたいっていう場合
ssh-keyscan
~/.ssh/known_hostsに無ければ登録する。これだと警告は出ない
if ! grep -q "remote_server" ~/.ssh/known_hosts 2>/dev/null; then
    # rsa or dsa
    ssh-keyscan -t dsa "remote_server" >> ~/.ssh/known_hosts
fi
接続時にオプション指定
警告はでるけど無視する(たぶんセキュリティ的にはよくない)
ssh -o StrictHostKeyChecking=no -l account -i ~/.ssh/id_dsa remote_server
設定ファイルに指定
StrictHostKeyChecking=noを~/.ssh/configに記載しておく
cat <<EOL > ~/.ssh/config
> Host *
> StrictHostKeyChecking no
> EOL
オプション指定しなくても有効になる

接続遮断防止

接続先サーバに null パケットを送信して、無操作時に勝手に接続が切れてしまうのを防ぐ(sshdの設定がそうなっている場合があったりするので).ssh/configに以下を記載する
ServerAliveInterval 60

パスワードなしで対象サーバにログイン

パスワード無しの公開鍵作成
まずはパスワードなしの鍵を作成する
# 標準では対話式だけど、コマンド一発でできるように
ssh-keygen -t dsa -C "non password key" -N "" -f ~/.ssh/id_dsa
これで~/.ssh 以下に
-rw------- 1 hoge hoge 668  8月 24 20:57 id_dsa     # 秘密鍵
-rw-r--r-- 1 hoge hoge 606  8月 24 20:57 id_dsa.pub # 公開鍵
というファイルが生成される。生成された公開鍵のほうをパスワードなしでログインしたいサーバのアカウントのホームディレクトリ以下の~/.ssh/authorized_keys に追加する。追加後はid_dsa.pubは必要ないので削除。
あとは対象サーバにパスワードなしでsshで接続できるか確認
ssh -l account -i ~/.ssh/id_dsa remote_server
パスワードありの公開鍵作成
鍵をどうしてもパスワードありにしたい場合。まずは鍵を作る
ssh-keygen -t dsa -C "password key" -N "hogehoge" -f ~/.ssh/id_dsa
id_dsa.pubをパログインしたいサーバのアカウントのホームディレクトリ以下の~/.ssh/authorized_keys に追加する。追加後はid_dsa.pubは必要ないので削除。ここは手順は同じ。

あとは接続できるか確認
ssh -l account -i ~/.ssh/id_dsa remote_server
Enter passphrase for key '/home/hoge/.ssh/id_dsa': <- ここにパスワード入力
とりあえずパスワード入力することでログインできることは確認。これで一度リモートからはログアウトし、ssh-agentを起動してみる。

ssh-agent起動
ssh-agent bash
ssh-agentに鍵の情報を覚えさす
ssh-add ~/.ssh/id_dsa
Enter passphrase for key '/home/hoge/.ssh/id_dsa': <- ここにパスワード入力
Identity added: /home/hoge/.ssh/id_dsa (/home/hoge/.ssh/id_dsa)
# これで再度ssh。パスワード入力なしでいけるはず
ssh -l account -i ~/.ssh/id_dsa remote_server
ちなみにssh-agentを落とすときは
eval $(ssh-agent -k)
これでパスワードありでも無しとおなじような扱いで接続できる

バージョン指定

# v2で
ssh -2 remote_server
秘密鍵から公開鍵を作成
当然ながら逆は無理
ssh-keygen -y -f ~/.ssh/id_dsa

暗号化

/etc/ssh/ssh_configを参照
grep Cipher /etc/ssh/ssh_config
#   Cipher 3des
#   Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc
使用できる暗号化の方法とデフォルトがどれになっているかわかる。指定したい場合は
ssh -c aes128-cbc remotehost
のようにすればよい。rsync + sshやscpなどの転送速度を気にする場合はcipherの指定をarcfourにすると早くなるようだ。ただし暗号化の強度は落ちるので自己責任。のようだ

tar

ファイルを追加

archive.tarというtarファイルがすでに存在するとして、hoge.txtをarchive.tarに追加したい場合
tar rf archive.tar hoge.txt

ファイルを削除

archive.tarの中からhoge.txtを削除したい場合
tar --delete -f arvhive.tar hoge.txt

一部のファイルだけ取り出す

archive.tarには以下のファイルがまとめられていて
tar tf archive.tar
hoge.txt
hogehoge.txt
hogehogehoge.txt
hogehogehoge.txtだけ取り出したい場合
tar xf archive.tar hogehogehoge.txt
というようにアーカイブのあとに取り出したいファイル名を指定する

アーカイブのリストに追加したサイズ

totalsオプションを使う
tar --totals -cpvf archive.tar hogehoge.txt hogehogehoge.txt
Total bytes written: 30720 (30KiB, 4.9MiB/s)

アーカイブするリストをファイルで指定

リストファイル指定オプションを使う(-T or --files-from FILE)
tar --totals --preserve -cvT archive.list -f archive.tar
archive.listにはファイルリストを一行ずつ記述する

除外するリストをファイルで指定

除外したいリストファイル指定オプションを使う(-X or --exclude-from FILE)
オプションで直接除外するのを指定する場合は--exclude FILEを指定
tar -cvX exclude.list -f archive.tar hogehoge.txt hogehogehoge.txt

更新されたファイルだけバックアップ

日ごとの差分バックアップをとるのに便利
tar --newer "2008-11-23 18:50:00" -cvf archive.tar hogehoge.txt hogehogehoge.tx

移動してtarする

アーカイブを取りたいファイル/ディレクトリが/home/hogeにある場合
cd /home/hoge
tar cvf /backup/hoge.tar file1 file2 dir1 dir2
とするのがめんどくさい場合-C, --directoryを指定する
cd /home/hoge
tar -C /home/hoge -cvf /backup/hoge.tar file1 file2 dir1 dir2

gzip + tar

tar.gzなファイルを展開/圧縮したいけど、zオプションが使えない場合。solarisとかだとそんな感じ
展開
gzip -dc hoge.tar.gz | tar xvf -
圧縮
tar cvf - hoge | gzip -f > hoge.tar.gz

ssh + tar

サーバ間で展開/圧縮データをやり取りしたりする時
from local to remote
tar -C /path/to -cpzf - . | ssh account@remote_server "tar -C /path/to xvfp -"
これはすぐに展開してしまうパターン。どっちかというとローカルのファイル/ディレクトリをリモートにコピーみたいな感じ。tarballとしてリモートに転送したい。だけど、一度ローカルにtarball作りたくない場合は、
tar -C /path/to -cpzf - .  | ssh account@remote_server "cat > /path/hogehoge.tar.gz"
とするとよい
from remote to local
逆にリモートのディレクトリをtarballとしてローカルに転送したい場合は逆をすればよい
ssh account@remote "cd path && tar cpfz - ." > hogehoge.tar.gz

sed

ファイル内の中途半端の改行コードを削除

テキストファイルをバイナリでアップしてしまったりして、たまにテキストファイルの改行部分が^Mみたいなのがはいってしまった時に削除する
#^M はターミナルで Ctl+v Ctl+m を入力
sed -i 's/^M//g' crlf.txt
これで再度viで対象ファイルを開くと正常に削除されている

自サーバのアドレス取得

ホスト名を取得したい場合はhostnameコマンドでいけるが、IPアドレスを取得するコマンドなんてないので
/sbin/ifconfig eth0 | grep "inet addr" | sed -e 's/.*inet addr:\([0-9.]*\) .*/\1/'
grepで結果を絞ってからsedする。interface部分は適時変更。linuxベースで確認しているので、ifconfigの結果が違う場合は当然使えない

html削除

根こそぎ削除
sed -e 's/<[^<>]*>//g' $file

date

日付表示のフォーマット

2008-10-15 02:02:20 みたいな感じで出力
date '+%Y-%m-%d %T' 
詳細はman dateをみてみる
何日前とか表示
昨日
date --date 'yesterday'
10日前
date '+%Y-%M-%d %T' --date '10 days ago'
10年後
date '+%Y-%M-%d %T' --date '10 years'
unixtime
date '+%s'
指定した日付のunixtime
date '+%s' -d "2009-02-17 11:51:01"
といろいろできるみたい

unixtimeから日付。dateに@$unixtime だそうな
date --date "@1325809488" "+%Y-%m-%d %H:%M:%S"

日付の設定

dateでもシステムの時間は変更できる
date -s '1999-12-31 11:59:59'
のようにすると日付変更できる。ただしrootのみ(まあこんなことあんまりせんだろうけど。普通はntpdかntpdateでしょう)

ファイルテスト演算子

といっても基本的なのじゃなくちょっと特殊なの

標準入力の検査

t
標準入力(0)が、対話的なターミナルと関連づけられている場合は終了コードは0(正常終了)
if [ -t 0 ]; then
    echo "適当に出力
else
    # 標準入力で受け取ったデータをそのまま出力
    cat -
fi
p
標準入力が名前付きパイプなら終了コードは0(正常終了)
if [ -p /dev/stdin ]; then
  # 標準入力で受け取ったデータをそのまま出力
  cat -
else
  echo "適当に出力
fi
/dev/stdinのかわりに/proc/self/fd/0, /dev/fd/0 でもいけるかも

変数の文字列長情報を調べる

結構よく使うのでメモ
z
ゼロバイトかチェック
if [ -z $str ]; then
  echo "\$str is zero length"
fi
n
0以上か調べる
if [ -n $str ]; then
  echo "\$str is not zero length"
fi

ファイルテスト

s
ファイルが存在し、サイズが1byte以上
file="/path/to/file"
if [ -s $file ]; then
  echo "\$file is exists and not zero length"
fi

プロセス関係

いろいろあるのでまとめて

top

メモリ使用量が多い順に表示
topが起動している状態でShift + m。ちなみにShift + oでどのフィールドでsortするか選択することもできる
更新秒数変更
Shift + dで変更。デフォルトは3秒

ps

一般的な使い方
#hogehogeアカウントが起動している情報を表示する。ただし、一行目(見出し)は非表示
ps -U hogehoge -o 'user,uid,gid,pid,ppid,rss,command' --no-heading
# hoge.plというスクリプトが起動している情報を表示
ps -C hoge.pl -o 'user,uid,gid,pid,ppid,rss,command' --no-headers
# tree状に全体表示
ps axlf
format
  • oで指定できるフィールド名。多いのでそのままコピペ
[-o format]
    -o オプションを使用すると、出力書式をユーザーが指定するこ と
    ができます。

    出力書式は、空白またはコンマで区切った引数のリストで指定しま
    す。 各 変数にはデフォルトのヘッダーがあります。等号と新しい
    ヘッダーのテキストを追加することによって、デフォルト の ヘッ
    ダーを上書きできます。引数の残りの文字は、ヘッダーテキストと
    して使用されます。コマンド行で指定した順番でフィールドが書き
    込まれ、カラムとして出力されます。フィールド幅は、少なくとも
    ヘッダーを表示できる幅 (デフォルト値または指定値) がシステム
    に よっ て選択されます。-o user=, のようにヘッダーテキストが
    NULL である場合、フィールド幅は少なくともデフォル ト の ヘッ
    ダーテキストを表示できる幅になります。すべてのヘッダーテキス
    トが NULL である場合、ヘッダー行が出力されません。

    POSIX ロケールでは、次の名前が認識されます。

    user  プロセスの実効ユーザーID。テキストのユーザーID を取 得
          でき、フィールド幅が足りる場合は、テキストのユーザーID
          になります。そうでない場合は、10 進数の ID に な り ま
          す。

    ruser プロセスの実ユーザーID。テキストのユーザーID を取得 で
          き、 フィー ルド幅が足りる場合は、テキストのユーザーID
          になります。そうでない場合は、10 進数の ID に な り ま
          す。

    group プロセスの実効グループ ID。テキストのユーザーID を取得
          でき、フィールド幅が足りる場合は、テキストのユーザーID
          になります。そうでない場合は、10 進数の ID に な り ま
          す。

    rgroup
          プロセスの実グループ ID。テキストのユーザーID を取得で
          き、 フィー ルド幅が足りる場合は、テキストのユーザーID
          になります。そうでない場合は、10 進数の ID に な り ま
          す。

    pid   プロセス ID の 10 進数値。

    ppid  親プロセス ID の 10 進数値。

    pgid  プロセスグループ ID の 10 進値。

    pcpu  最近のある期間において、使用できる CPU 時間に対して 実
          際 に使用された CPU 時間の割合 (単位: %)。「最近」およ
          び「使用できる CPU 時間」は不定で、場合によって異な り
          ます。

    vsz   仮想メモリー中のプロセスの合計サイズ (単位: キロバイト
          )。

    nice  プロセスの、システムスケジューリング優先順位を表す  10
          進数値。nice(1) を参照してください。

    etime POSIX ロケールにおける、プロセスが開始されてからの経過
          時間。書式は次のとおりです。

          [[dd-]hh:]mm:ss

    dd    日
    hh    時間
    mm     分
    ss     秒

    dd フィールドの値は 10 進の整数です。hh、mm、ss フィー ル ド
    は、ゼロによって左揃えされた 2 桁の 10 進整数です。

    time  POSIX ロケールにおける、プロセスの累積 CPU 時間。書 式
          は次のとおりです。

          [dd-]hh:mm:ss

          dd、hh, mm、ss フィールドは、etime と同様です。 etime
          の説明を参照してください。

    tty   プロセスの制御端末の名前。書式は who(1) コマンドによっ
          て使用されるものと同じです。

    comm  実行されているコマンドの、文字列としての名前  (argv[0]
          の値)。

    args  文字列としての、コマンドとそのすべての引数。実装によっ
          てフィールド幅までに切り捨てられることがあります。これ
          は実装に依存します。この文字列が、コマンドが起動された
          ときにコマンドに渡された引数であるか、またはアプリケー
          ションによって変更された引数であるかは、不定です。アプ
          リ ケーションは、引数リストを変更できて、その変更を ps
          の出力に反映することに依存しません。Solaris 実装では、
          この文字列は 80 文字以内に限定され、コマンドが起動され
          たときにコマンドに渡された引数となります。

    Solaris 実装では、次の名前が認識されます。

    f     プロセスに関連付けられたフラグ (16 進数、加法的)。

    s     プロセスの状態。

    c     スケジューリングのためのプロセッサ利用 (旧仕様)

    uid   プロセスの実効ユーザーID (10 進整数)

    ruid プロセスの実ユーザーID (10 進整数)

    gid   プロセスの実効グループ ID (10 進整数)

    rgid  プロセスの実グループ ID (10 進整数)

    projid
          プロセスのプロジェクト ID (10 進整数)

    project
          プロセスのプロジェクト ID (取得できる場合はテキス ト。
          そうでない場合は 10 進整数)

    sid   セッションリーダーのプロセス ID

    taskid
          プロセスのタスク ID

    class プロセスのスケジューリングクラス

    pri   プロセスの優先順位 (数値が大きいほど優先順位が高い)

    opri  プロセスの廃止優先順位 (数値が小きいほど優先順位が高い
          )

    lwp   lwp ID (10 進数)。1 行に 1 つの進行中の軽量プロセス が
          示されます。

    nlwp  軽量プロセスの数

    psr   プロセスまたは軽量プロセスがバインドされているプロセッ
          サの数

    pset  プロセスまたは軽量プロセスがバインドされているプロセッ
          サセットの ID

    addr  プロセスのメモリーアドレス

    osz   仮想メモリー中のプロセスの合計サイズ (単位: ページ)

    wchan プロセスが休止中のイベントのアドレス (- の場合、プロセ
          スは動作中)

    stime プロセスの開始時刻または開始日。空白なしで出力さ れ ま
          す。

    rss   プロセスの常駐の設定サイズ (単位: キロバイト)

    pmem  マシン上の物理メモリーに対する、プロセスの常駐の設定サ
          イズの割合 (単位: %)

    fname プロセスの実行可能ファイルのベース名の先頭 8 バイト

    comm および args だけに、空白文字を含めることがで き ま す。
    Solaris 実装の変数およびその他すべての名前には、空白文字を含
    めることができません。

    POSIX ロケールで使用されるデフォルトヘッダーとそれに対応する
    書式指定子は、次のとおりです。
    __________________________________________________________________
   | 書式             デフォルト    | 書式             デフォルト    |
   | 指定子           ヘッダー      | 指定子           ヘッダー      |
   | args             COMMAND       | ppid             PPID          |
   | comm             COMMAND       | rgroup           RGROUP        |
   | etime            ELAPSED       | ruser            RUSER         |
   | group            GROUP         | time             TIME          |
   | nice             NI            | tty              TT            |
   | pcpu             %CPU          | user             USER          |
   | pgid             PGID          | vsz              VSZ           |
   | pid              PID           |                                |
   |________________________________|________________________________|

    Solaris 実装における書式指定子と対応するデフォルト ヘッ ダー
    は、次のとおりです。

    __________________________________________________________________
   | 書式             デフォルト    | 書式             デフォルト    |
   | 指定子           ヘッダー      | 指定子           ヘッダー      |
   | addr             ADDR          | projid           PROJID        |
   | c                C             | project          PROJECT       |
   | class            CLS           | psr              PSR           |
   | f                F             | rgid             RGID          |
   | fname            COMMAND       | rss              RSS           |
   | gid              GID           | ruid             RUID          |
   | lwp              LWP           | s                S             |
   | nlwp             NLWP          | sid              SID           |
   | opri             PRI           | stime            STIME         |
   | osz              SZ            | taskid           TASKID        |
   | pmem             %MEM          | uid              UID           |
   | pri              PRI           | wchan            WCHAN         |
   |________________________________|________________________________|

【使用例】
    例 1: ps コマンドの例

    example% ps -o user,pid,ppid=MOM -o args

    上記のコマンドによって、POSIX ロケールでは以下の内容が出力さ
    れます。

    USER  PID   MOM   COMMAND
    helene  34    12   ps -o uid,pid,ppid=MOM -o args
    切り捨てが発生する可能性があるため、COMMAND の内容は必ずしも
    上記の例と一致しません。

【環境】
    ps の実行に影響を与える環境変数  LC_CTYPE、 LC_MESSAGES、
    LC_TIME、NLSPATH についての詳細は、environ(5) を参照してくだ
    さい。

    COLUMNS
          画面の水平方向のサイズとして、システムが決定する値の代
          わりに使用する値を定義します。この値により、表示するテ
          キストカラム数が決まります。
正直、オプションが多すぎるので詳細は とかみるとよいかも

fuser

とあるファイルがどのプロセスが使用しているか知りたい時とかによく使う
簡単な使い方
viのswapファイルはどのユーザーが使っているプロセスか調べる。-uで誰が使用しているかわかる
/sbin/fuser -u /home/holly/.hoge.pl.swp
/home/holly/.hoge.pl.swp:  8372(holly)
どのプロセスもつかんでいない場合は何も表示されない
つかんでいるプロセスをkill
/sbin/fuser -k /home/holly/.hoge.pl.swp
デフォルトでシグナルはSIGKILLが送信されるので変更したい場合は
/sbin/fuser -k /home/holly/.hoge.pl.swp -TERM
などと指定する。killするか確認する場合は
/sbin/fuser -i -k /home/holly/.hoge.pl.swp -TERM
-iを指定するとkillする前に確認メッセージが表示される
とあるportを使用しているプロセスを調べる
/sbin/fuser -nc tcp 25
                      USER        PID ACCESS COMMAND
 25/tcp:              root       1541 F....  master
-nはtcp/udpなどを指定するためのオプション。-cはマウントポイントおよびそのマウントポイントの下にあるファイルの使用状況を表示。この場合だとpostfixのmasterプロセスが使用していることがわかる

pgrep

プロセス名からプロセスIDなどを取得するときに使う
あいまいmatch
pgrep -l hoge
1842 hoge.pl
1843 hogehoge.pl
この場合だとプロセス名にhogeが含まれるpidとプロセス名が表示される
完全match
実効ユーザー、完全なコマンドライン名でpgrepする場合は
pgrep -u holly -x -l -f "/usr/bin/perl /home/admin/hoge.pl"
とする。オプションはこんな感じ
  • -u プロセスを動かしているユーザー名を指定
  • -f デフォルトはプロセス名にマッチだが、コマンドライン全体にマッチする
  • -x -fで指定した完全一致したプロセス名(コマンドライン)にマッチする
  • -l プロセス名を表示する

pkill

pgrepはプロセス名からpidなどの情報を表示するが、pkillはpgrepのkill版
完全matchしたプロセスをkill
pkill -u admin -x -f "/usr/bin/perl /home/admin/hoge.pl"
あいまい指定でもkillできるけど、killしたくないプロセスまでkillしてしまう可能性があるので、この方が確実。pgrepで一度確認するのがよい。
シグナル指定
デフォルトではTERMなので指定したい場合は
pkill -KILL -u admin -x -f "/usr/bin/perl /home/admin/hoge.pl"
のようにkillと同じような指定方法でいい

diff

差分を調べる時によく使う

ファイルの差分

こんなスクリプトがあったとして
# test.sh
#!/bin/sh
 
date=$(date +%Y%m%d-%H%M%S)
echo "now is $date"
こんなのに変更した
#test_new.sh
#!/bin/sh

echo "now is $(date +%Y%m%d-%H%M%S)"
変更分の差分をとりたい場合
diff -u test.sh test_new.sh
--- test.sh     2008-09-04 00:59:06.000000000 +0900
+++ test_new.sh 2008-09-04 01:01:25.000000000 +0900
@@ -1,4 +1,3 @@
 #!/bin/sh

-date=$(date +%Y%m%d-%H%M%S)
-echo "now is $date"
+echo "now is $(date +%Y%m%d-%H%M%S)"
とすると差分が表示される。出力形式はいろいろあるが、-nがなんとなくわかりやすい。
diffの結果からpatchファイルを作ることができるので
diff -u test.sh test_new.sh > test.patch
とするとpatchファイルのできあがり。test_new.shを削除したあと
patch -p0 -d . < test.patch
とするとtest.shはpatchがあたり、test_new.shとの差分がなくなる

ディレクトリの差分

ディレクトリ内部のファイル全てに対してdiffしたい場合は
diff -ru dir1 dir2
diff -ru dir1/a/b/hogehoge.txt dir2/a/b/hogehoge.txt
--- dir1/a/b/hogehoge.txt       2008-09-04 01:07:38.000000000 +0900
+++ dir2/a/b/hogehoge.txt       2008-09-04 01:08:12.000000000 +0900
@@ -1 +1,2 @@
 hogehoge
+alalala
Only in dir2: aaa.txt
オプションに-rを付けると再帰的にdiffしてくれるが差分結果がぞろぞろと出てきてしまうので、
diff -rq dir1 dir2
Files dir1/a/b/hogehoge.txt and dir2/a/b/hogehoge.txt differ
Only in dir2: aaa.txt
オプションに-qを付けると詳細な差分は表示されなくなる。
ただし↑の方法では一方にしか存在しない、つまり追加または削除されたファイルは記録されないので、追加または削除されたファイルも記録するためには以下のようにする
diff -ruN dir1 dir2 > dir.patch
オプションに-Nを付けると、ディレクトリを比較する際、片方のディレクトリにのみファイルが存在していたらもう片方のディレクトリには同名の空っぽのファイルがあるように動作する。これでディレクトリ単位のpatchファイルを作成可能。戻すときはファイルのpatch手順と同じでよいが、ファイルの追加はされても削除が行われません。ファイルの削除も再現するには以下のように-Eをつける
patch -p0 -d . -E < dir.patch

diffでファイルが違うかどうかだけ知りたい

オプション-qもしくは--briefを使う。ディレクトリ単位でdiffする場合はたいがいファイルの詳細な差分情報はいらないので(ファイルが違うかどうかだけ知りたいので)このオプションを使うと内容が違う、もしくは片方のディレクトリにしかないファイルの名前のみでてくる。
#-rはディレクトリを再帰的に
diff -rq /path/to/foo /path/to/bar
Files /path/to/foo/hoge.pl and /path/to/bar/hoge.pl differ
Only in /path/to/foo: hage.pl
Filesから始まっている行は違いのファイル同士。Onlyから始まっているのは片方のディレクトリにしかないファイル

lv

nkfのかわりに文字コード変換によく使ったり。古いOSとかだと入ってなかったりするけど

文字コード変換して内容を表示

eucのファイルをutf8で表示する。PAGERとしてlessが使われているっぽい
lv -Iej -Ou8 euc.txt
よく使うオプション
  • -I 入力文字コード
  • -O 出力文字コード

さらに指定する文字コード
  • a auto-select
  • c iso-2022-cn
  • j iso-2022-jp
  • k iso-2022-kr
  • ec euc-china
  • ej euc-japan
  • ek euc-korea
  • et euc-taiwan
  • u7 UTF-7
  • u8 UTF-8
  • l1..9 iso-8859-1..9
  • l0 iso-8859-10
  • lb,ld,le,lf,lg iso-8859-11,13,14,15,16
  • s shift-jis
  • b big5
  • h HZ
  • r raw mode

文字コード変換

リダイレクトで書き出すとファイルの文字コード変換することができる
lv -Iej -Ou8 euc.txt > utf8.txt
一括で複数のファイルの文字コードを変換したい場合は
for f in *.txt; do
  conv=$f.utf8
  lv -Ia -Ou8 $f > $conv
  mv -f $conv $f
done

uuidgen

最近のOSだとデフォルトで入ってるのかも。ランダムな文字列(みたいなの?)を生成したい場合
uuidgen
a53d7838-3c53-4b02-a98f-b4b0679f3a45
これだけでいいんだけど、このうちの先頭8byteだけでいいし、-(ハイフン)はいらない場合は
uuidgen | sed -e 's/-//g' | cut -c 1-8
186ec9d1
こんなふうにmd5の結果っぽくなるので、それなりにランダムっぽい文字列を作りたい場合は、perlねたランダムな文字列を生成したいを見るとよい

cd

ねたがなさそうでいろいろあったり

前いたディレクトリに移動する

cd -

pushd, dirs, popd

pushd
cdとにたようなことをするが、実行時のカレントディレクトリと行き先のディレクトリをディレクトリスタックに保存する
# /binに移動
pushd /bin
# /usr/binに移動
pushd /usr/bin
# /varに移動
pushd /var
引数なしで実行した場合は、ひとつ前のディレクトリに戻り、実行時のカレントディレクトリはディレクトリスタックのいちばん前に回される。
dirs
ディレクトリスタックに保存している内容を表示する
dirs
/var /usr/bin /bin ~
何がうれしいかというと今まで移動したディレクトリの名前が/path/to/long/path/nameと長ったらしい名前だとして、戻りたい場合にcd /path/to/long/path/name/.... などと入力しなくてもディレクトリスタックに移動した場所が保存されているので、簡単に戻ることができる。/usr/binに戻りたい場合はディレクトリスタックインデックスが1なので(配列の添え字の考え方と同じ。前から0番目)
pushd +1
とするだけで戻ることができる。
popd
ひとつ前のディレクトリに戻り、実行時のディレクトリはディレクトリスタックから削除する。簡単なので特に説明はなし

dd

穴あきファイル

こんなもん作ることないだろうと思いつつ、最近いろいろとお世話になっているので
dd if=/dev/zero of=sparse.txt seek=1024 bs=100M count=0
これで100GBの穴あきファイルが作成できる。穴あきファイルをlsすると
LANG=C ls -hl sparse.txt
-rw-r--r-- 1 root root 100G Dec  1 01:09 sparse.txt
といっけん100Gのファイルのようにみえるが
LANG=C ls -hsl sparse.txt
0 -rw-r--r-- 1 root root 100G Dec  1 01:09 sparse.txt
ブロックサイズを確認するとまったく使用されていないことがわかる。du, dhなどでも同じ結果になる

od

8進dumpとか16進dumpとかする。たまに使う。デフォルトだと8進数dumpだけになる
cat hello.txt
hello world
これをodすると
 od hello.txt
0000000 062550 066154 020157 067567 066162 005144
0000014
となる。正直よくわからないので
od -tcx1 hello.txt
0000000   h   e   l   l   o       w   o   r   l   d  \n
        68 65 6c 6c 6f 20 77 6f 72 6c 64 0a
0000014
tcx1がおすすめ。どこかでみた。がそのとおり
x[長さ]	16進数表記
d[長さ]	10進数表記
o[長さ]	8進数表記
c	文字表記 (改行コードなどは \r や \n のように表記)
a	文字表記 (改行コードなどは CR や LF のように表記)
長さはデフォルトで2byteになるので整理すると↓のようになる
-tx1 … 1バイト単位で 16進数表記
-tx2 … 2バイト単位で 16進数表記
-tx4 … 4バイト単位で 16進数表記
-td1 … 1バイト単位で 10進数表記
-td2 … 2バイト単位で 10進数表記
-td4 … 4バイト単位で 10進数表記
-tx … (省略したので) 2バイト単位で 16進数表記
-td … (省略したので) 2バイト単位で 10進数表記

split

ファイル分割でいろいろ

行数ごとに分割

たとえば100行あるファイル(num.txtとする)を10行ずつに分割したい場合は
split -l 10 num.txt
とする。lsすると
num.txt  xaa  xab  xac  xad  xae  xaf  xag  xah  xai  xaj
と存在している。復元したい場合は
cat xa* > num.txt.concat
とするとよい。ハッシュ値をmd5sumで確認すると同じになっていることが確認できる

byte数で分割

  • bで指定する

分割してできるファイル名を指定

デフォルトではxa**となるようなので、自分で指定したい場合はprefixを指定する
split -l 30 num.txt split.
と指定した場合は
split.aa  split.ab  split.ac  split.ad
と分割されるようになる

sudo

あまりたいしたことはかかない

標準入力からパスワードを渡したい

  • Sを指定する。実行したいコマンドなども標準入力から受け付けるようだ
echo -e 'password\ncat /etc/shadow' | sudo -S -s
sudoのデフォルト設定だと5分間は一度認証成功するとその後はパスワード聞かれないので、5分以内に2回目の実行をする場合は注意。上記例で実行すると
/bin/bash: line 1: password: command not found
uid=0(root) gid=0(root) 所属グループ=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
とコマンドとして認識される

curl

最近wget を使って説明しているのが少ないので試してみる。よく使われるのは-LO
curl -LO http://$url/index.html

よくつかうオプション

-L --location 指定しなくてもよさそうだが。URLを指定
-O --remote-name remote-nameでローカルに保存する
-o --output 保存するファイル名
-s --silent 出力を抑制
--insecure httpsでアクセスする時に怪しい証明書でもエラーにしない
-A --user-agent
--user 引数なしだと対話形式 <user>を指定した場合は対話形式でパスワード、<user>:<pass> で指定した場合は対話はなく実行 

-1/--tlsv1         Use TLSv1 (SSL)
-2/--sslv2         Use SSLv2 (SSL)
-3/--sslv3         Use SSLv3 (SSL)

-d/--data <data> formdataを渡す。こんな感じで。"name=Rafael%20Sagula&phone=3320780"
-e/--referer referer

REST APIのテストするとき

GETはいいとしてPOST/PUT/DELETEしたい。特にPUT/DELETE
curl -X PUT --data name=kurt --data band=nirvana http://$apiurl/
Xオプションでメソッドを指定すればよい。POSTは明示的に指定しなくても--dataがあればPOSTとみなされる

jsonを返すURLに対して

たいがい「ajaxならば」な処理でjsonを返す処理をしているのがおおいはず。
X-Requested-With: HTTP_X_REQUESTED_WITH or XMLHttpRequest or XmlHttpRequest
を含んでいれば、xhrな処理をしてくれるはずなので
# cakephpで構築したやつの場合。ログイン認証cookieとxhrなrequest headerを送る。ついでにuseragentもおくる
curl -H "Cookie: CAKEPHP=xxxxxxxx" -H "X-Requested-With: HTTP_X_REQUESTED_WITH" -A "Mozilla/5.0 (Windows NT 5.1; rv:2.0) Gecko/20100101 Firefox/4.0" -v -X POST http://$domain/show/:id
というふうに-Hにrequest headerを指定する

stty

入力した文字列をコンソールに出力しない

stty -echo
passwdコマンドとかはこんなことしてると思う
逆は
stty echo
とか

相対パスを絶対パスに変換

もちろん/etc/passwdと表示される
file=../../../etc/passwd
echo $(cd $(dirname $file) && pwd)/$(basename $file)

プロセスリソース制限系

nice

よく使う。CPUの優先率を操作。-20(最優先)から19(一番あと)まで指定
# -20 とかで指定したい場合は nice -n -20 /path/to/command とする
# -nは--adjustment=Nでもよい
nice -n10 /path/to/command

renice

niceを書いたからおまけ。すでに動いているプロセスの優先度を変更
renice [adjustment] -p $PID
その他、プロセスに対してではなく
-u $user
-g $processgroup
||
というような指定もできるようだ
**ionice
最近知った
=|BOX|
ionice -c2 -n7 /path/to/command
使い方。-nが優先度で数値が大きいほど実行度が後回しになる。scheduling classはよくわからないが、3は他のプロセスがioに負荷を少しでもかけている場合はそれが終わるまで待つらしい。ただしそのプログラムが終わらない。ということになりかねないのであんまりやらないほうがいいような気がする
-n      Class data (typically 0-7, lower being higher prio)
-c      Scheduling class
                1: realtime, 2: best-effort, 3: idle
-p      Process pid
-h      This help page

rsync

いまさらながらなので、基本的なことは書かない

rsync3.x

とにかくいいらしい。centosのyumでインストールすると2.x系なのでrpmforgeあたりであるか確認

対象サーバの負荷を抑えながら実行

どこかで見たやつをそのまま。
rsync --bwlimit=3096 --rsync-path="ionice -c2 -n7 nice -n19 rsync" -ave "ssh -c arcfour" /backup/ remote:/path/to/backup/

tcpdump

よく使う方法

年に何回かは出番がくる。例
# -n 接続元のIPアドレスの名前解決をしない
# -x 16進数で表示
# -X ASCIIで表示
# -i dumpするinterfaceを指定
# -s パケットから取り出すデータの長さ。byte指定
tcpdump -nxX -i eth0 -s2000 port 80

結果をpipeで渡す場合

bufferingしないように-lをつける
tcpdump -nxX -i eth0 -s2000 -l port 80 | tee tcpdump.log

binary log

wをつける
tcpdump -nxX -i eth0 -s2000 -w tcpdump-bin.log port 80
出力した結果はそのままではよめないので、
tcpdump -n -r tcpdump-bin.log
とすると読めるようになるがよくわからないので、調べておく。あまりみることないと思うし

詳細に

v, vvをつける
tcpdump -nxX -i eth0 -s2000 -vv port 80

組合わせ

host + port
 tcpdump -nxX -s2000 -vv host $host and port 80
src/dst
hostの前などにつけると、送信だけ(src)、受信だけ(dst)、というように挙動を変更できる。デフォルトは双方向キャプチャしている
# $hostからの接続でport80なら
tcpdump -nxX -s2000 -vv host $host and dst port 80

# $hostへの接続でport80なら
tcpdump -nxX -s2000 -vv src host $host and port 80
http://www.tcpdump.org/tcpdump_man.htmlをみればわかるが、udpやsubnet単位でのキャプチャも可能

関数登録

登録

コンソールで以下のように実行すればよい
hogehoge() {
    # something to do...
}
functionをつかってもいいがそこは好みで

登録している関数一覧

declare -f

削除

unalias。aliasの削除以外でも使える
unalias -f hogehoge