Linuxコマンド
vi(vim)
Linuxをおぼえるときは、コマンドもそうだけど、vi(vim)の使い方をおぼえるのが大事な気がする。
サーバやらツールのやらの設定ファイルの編集がスムーズにできないと、それだけでいやになってしまうので。
自分は、まずは、Windows版のvimで使い方をおぼえた。5時間×2日で、自転車の練習のようにおぼえた。正直、これだけではまだまだ慣れるまではいかないのだけど、手は動くようになる。メモをつくりながら、便利な操作をどんどん調べて、使っていくとよいとおもう。
基本の操作
- 行番号を表示する。
- :set number
- 指定した行へ移動する。
- 最後の行へ
- G
- 10行目へ
- 10G
- 最後の行へ
何単位で何をするのか?を意識することが必要。
単位と処理を組み合わせる。
- 文字単位の処理
- 現在のカーソル位置から6文字削除右へ
- 6dl
- 現在のカーソル位置から6文字削除右へ
- 単語単位の処理
- 現在のカーソル位置から9単語移動右へ
- 9w
- 現在のカーソル位置から9単語移動右へ
- 行単位の処理
- 現在のカーソルのある行をヤンク(コピー)
- :yy
- 10行目をヤンク(コピー)
- :10y
- 21行目から30行目をヤンク(コピー)
- :21,30y
- ヤンクしたものを貼り付けるは、pまたはP
- 31行目から40行目をを置換
- :31,40s/abc/efg/g
- 41行目から最後の行まで削除
- :41,$d
- 現在のカーソルのある行をヤンク(コピー)
- 全行の処理
- 全行を置換
- 全行を表す記号は%
- :%s/abc/efg/g
- :%s;/pqr;/stu;g(置換する単語に/を含む場合は、/ではない単語で区切る。ここでは、;)
- 全行を置換
ファイル
ls
- ls -ltr
- タイムスタンプの逆順でソートして表示
- このオプションだとファイルが多いディレクトリで、今、更新したファイルが下に表示されるので、更新したファイルを確認しやすい。
- ls -l --time-style=+'%Y-%m-%d %H:%M:%S'
- タイムスタンプ表示のフォーマットを指定
basename
eiichi@ubuntu-desktop:~/test$ basename /home/eiichi/test/a.txt a.txt
FILE_NAME=$(basename $0)
dirname
eiichi@ubuntu-desktop:~/test$ dirname /home/eiichi/test/a.txt
/home/eiichi/test
DIR_PATH=$(dirname $0)
ただし、シェルスクリプトの呼び出し方によって、$0の値は変わるので注意
ためしに、作業ディレクトリ/bin/get-path.shを作成する。
#!/bin/bash echo $0
実行すると、
- 相対パスで実行
- フルパスで実行
- コマンドパスに通してで実行
で、$0の値は変わる。
eiichi@ubuntu-desktop:~/Programming/shellscripts$ bin/get-path.sh bin/get-path.sh eiichi@ubuntu-desktop:~/Programming/shellscripts$ $(pwd)/bin/get-path.sh /home/eiichi/Programming/shellscripts/bin/get-path.sh eiichi@ubuntu-desktop:~/Programming/shellscripts$ PATH=$PATH:$(pwd)/bin eiichi@ubuntu-desktop:~/Programming/shellscripts$ get-path.sh /home/eiichi/Programming/shellscripts/bin/get-path.sh
readlink
フルパスを取得するためには、
readlink -f ファイルパス
コマンドを検索
which
ファイルを検索
find
ファイルの検索ではとても便利。検索条件を指定するためのオプションが豊富。重い処理になることもあるので、本番サーバや大勢がつかっているサーバで実行するときは注意。
- find . -name 検索ファイル名 -print
- 名前で検索
- find . -type d -print
- ディレクトリのみ
- find . -size +NNNN -print
- ファイルサイズがNNNN以上
単なる検索だけでなく、ファイルやディレクトリを抽出して、それらに対してコマンドを適用するのがとても便利。
grepと組み合わせると、さらにファイル名を正規表現で抽出できる。
xargsと組み合わせると、検索したファイルに対して、削除など、なんらかの処理を実行できる。xargsの%は、置換文字列
locate
高速な検索ができる。
ただし、事前に
updatedb
の実行が必要。
ファイルの中の文字列を検索
ファイルを圧縮および解凍
tar
圧縮
$ ls -la aaaa/bbbb/cccc/ 合計 8 drwxr-xr-x 2 eiichi eiichi 4096 2012-10-25 23:54 . drwxr-xr-x 3 eiichi eiichi 4096 2012-10-25 23:53 .. -rw-r--r-- 1 eiichi eiichi 0 2012-10-25 23:54 xxxx.txt -rw-r--r-- 1 eiichi eiichi 0 2012-10-25 23:54 yyyy.txt $ tar cvfz cccc.tar.gz -C aaaa/bbbb/cccc . ./ ./yyyy.txt ./xxxx.txt $ tar cvfz cccc.tar.gz -C aaaa/bbbb cccc cccc/ cccc/yyyy.txt cccc/xxxx.txt
展開
$ tar xvfz cccc.tar.gz cccc/ cccc/yyyy.txt cccc/xxxx.txt $ ls -la cccc 合計 8 drwxr-xr-x 2 eiichi eiichi 4096 2012-10-25 23:54 . drwxr-xr-x 17 eiichi eiichi 4096 2012-10-25 23:58 .. -rw-r--r-- 1 eiichi eiichi 0 2012-10-25 23:54 xxxx.txt -rw-r--r-- 1 eiichi eiichi 0 2012-10-25 23:54 yyyy.txt $ tar xvfz cccc.tar.gz -C eeee/ffff/ cccc/ cccc/yyyy.txt cccc/xxxx.txt $ ls -la eeee/ffff/cccc/ 合計 8 drwxr-xr-x 2 eiichi eiichi 4096 2012-10-25 23:54 . drwxr-xr-x 3 eiichi eiichi 4096 2012-10-26 00:00 .. -rw-r--r-- 1 eiichi eiichi 0 2012-10-25 23:54 xxxx.txt -rw-r--r-- 1 eiichi eiichi 0 2012-10-25 23:54 yyyy.txt
ドキュメントを検索
ファイル名の一括変更
for f in $(ls | grep 20110901); do mv $f $(echo $f | sed 's/20110901/20110831/'); done
rename 's/20110831/20110830/' *
文字列の処理
sed
置換して、ファイルの内容はそのまま
sed -e 's/aaaa/bbbb/g' ファイルパス
置換して、ファイルの内容を上書き
sed -i 's/aaaa/bbbb/g' ファイルパス
後方参照
$ echo '123abc456' 123abc456 $ echo '123abc456' | sed -e 's/\([0-9]\+\)\(.[a-z]\+\)\([0-9]\+\)/\1 \3/g' 123 456
perl
クォーテーションを、後方参照で取り除いてみる
$ echo "'a'" 'a' $ echo "'a'" | perl -i -p -e "s/'(.+)'/\$1/g" a $ echo '"a"' "a" $ echo '"a"' | perl -i -p -e 's/"(.+)"/$1/g' a
cut
- echo 'aaaa:bbbb:cccc' | cut -d':' -f1,3
awk
CSVファイルの読み込み
cat awk-test.csv 11,12,13,14 21,22,23,24 31,32,33,34 awk -F',' '{print $2":"$3}' awk-test.csv 12:13 22:23 32:33
10個おきに改行する。awkでは、NRは行番号を表している。
seq 1 20 | awk 'NR % 10 == 0 {printf("%s\n", $0)} NR % 10 != 0 {printf("%s ", $0)}' 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
シェルスクリプト中で、シェル変数をわたす
with-awk.sh #!/bin/bash LEFT_DECO="****++++" RIGHT_DECO="+++++****" awk -v LD="$LEFT_DECO" -v RD="$RIGHT_DECO" '{print LD" "$0" "RD}' test.txt
test.txt aaaaaaa bbbbbbb ccccccc ddddddd
eiichi@ubuntu-desktop:~/Programming/shellscripts$ ./with-awk.sh ****++++ aaaaaaa +++++**** ****++++ bbbbbbb +++++**** ****++++ ccccccc +++++**** ****++++ ddddddd +++++****
awkの関数もあるよ
sub 最初に見つかった文字列だけ置換
echo "AaAa BBBB CCCC" | awk -F' ' '{x=$1;sub("a", "A", x);printf("%s-%s-%s\n", x, $2, $3)}' AAAa-BBBB-CCCC
gsub 正規表現で、見つかった文字列を全部置換
echo "AaAa BBBB CCCC" | awk -F' ' '{x=$1;gsub("a", "A", x);printf("%s-%s-%s\n", x, $2, $3)}' AAAA-BBBB-CCCC
何かの数を数える
ソート
eiichi@ubuntu-desktop:~$ seq 1 15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-rで逆順にする。
eiichi@ubuntu-desktop:~$ seq 1 15 | sort -r
9
8
7
6
5
4
3
2
15
14
13
12
11
10
1
たしかにソートされてるんだけど、期待と違う。
-nオプションをつける
eiichi@ubuntu-desktop:~$ seq 1 15 | sort -nr
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
期待通りになった。
tsvファイルなどで、特定の列をソートすることもできる。
タブがデリミタになっている場合
sort -t$'\t' -k2
日時
date
$ date 2012年 10月 25日 木曜日 00:01:24 JST $ date +'%Y-%m-%d %H:%M:%S' 2012-10-25 00:01:32 $ date -d '2013-01-02 12:34:56' +'%Y%m%d%H%M%S' 20130102123456 $ date -d '2013-01-02 12:34:56 5 days' +'%Y%m%d%H%M%S' 20130107123456 $ date -d '2013-01-02 12:34:56 2 months ago' +'%Y%m%d%H%M%S' 20121102123456
日時を比較したいときは、エポックからの秒数になおす
$ A=$(date +'%s') $ B=$(date +'%s') $ echo $A 1351091129 $ echo $B 1351091135 $ test $A -lt $B $ echo $? 0 $ test $A -eq $B $ echo $? 1 $ test $A -gt $B $ echo $? 1
日時を比較したいとき、bashであれば、'<'や'>'も使える。
日時というか文字列の比較になる。
$ test '2014-01-01' '<' '2014-01-01' $ echo $? 1 $ test '2014-01-01' '<' '2014-01-02' $ echo $? 0
日付を連番で出力 while
date-seq-a.sh #!/bin/bash START_DATE='2014-01-01' END_DATE='2014-01-10' CURRENT_DATE=$START_DATE COUNT=0 while [ $CURRENT_DATE '<' $END_DATE -o $CURRENT_DATE = $END_DATE ] do echo $CURRENT_DATE COUNT=$(($COUNT + 1)) CURRENT_DATE=$(date -d "$START_DATE $COUNT days" +'%Y-%m-%d') done
$ ./date-seq-a.sh 2014-01-01 2014-01-02 2014-01-03 2014-01-04 2014-01-05 2014-01-06 2014-01-07 2014-01-08 2014-01-09 2014-01-10
日付を連番で出力 seq
date-seq-b.sh #!/bin/bash START_DATE='2014-01-01' END_DATE='2014-01-10' START_EPOCH_TIME=$(date -d $START_DATE +'%s') END_EPOCH_TIME=$(date -d $END_DATE +'%s') COUNT=$(((END_EPOCH_TIME - START_EPOCH_TIME) / 86400)) seq 0 $COUNT | xargs -I{} date -d "$START_DATE {} days" +'%Y-%m-%d'
$ ./date-seq-b.sh 2014-01-01 2014-01-02 2014-01-03 2014-01-04 2014-01-05 2014-01-06 2014-01-07 2014-01-08 2014-01-09 2014-01-10
フォーマット
コマンドを補助するコマンド
xargs
このページのほかのコマンドの例でもxargsをちらほらつかっている。
find . -type f -print0 | xargs -0 mv -t to-dir
time
あるコマンドの処理時間を計測しつつ、そのコマンドを実行する。
$ time wget http://www.google.co.jp --2014-02-15 03:14:10-- http://www.google.co.jp/ www.google.co.jp (www.google.co.jp) をDNSに問いあわせています... 173.194.126.183, 173.194.126.191, 173.194.126.184, ... www.google.co.jp (www.google.co.jp)|173.194.126.183|:80 に接続しています... 接続しました。 HTTP による接続要求を送信しました、応答を待っています... 200 OK 長さ: 特定できません [text/html] `index.html.2' に保存中 [ <=> ] 11,274 --.-K/s 時間 0.001s 2014-02-15 03:14:10 (11.0 MB/s) - `index.html.2' へ保存終了 [11274] real 0m0.148s user 0m0.027s sys 0m0.055s
文字コード
- file ファイルパス
- 改行コードが、LFならば、なにも表示しない。
- 改行コードが、CR+LFならば、そのように表示してくれる。
- nkf -g ファイルパス
特に、改行コード
- od -c
- 改行コード用じゃないんだけど、改行コードも見やすく表示される
文字コード変換
ユーザ管理
useradd
usermod
- usermod -g グループ名 ユーザ名
- デフォルトのグループを変更
- usermod -G グループ名 ユーザ名
- グループにこのユーザを追加
cat /etc/group
で確認
userdel
指定したタイミングで実行
cron
- いつ、どのコマンドを実行したいのか設定ファイルに記述して利用する
- cron本体のプロセスは、root権限で実行されるが、個々の処理は、該当ユーザの権限で実行される。
- cronの設定ファイル自体がユーザごとに用意される。
- 設定ファイルの編集
- 実行したいユーザになって、以下のコマンドで、設定ファイルを編集する。
- crontab -e
- 設定ファイルには、PATHのような、変数も記述できる。
- デフォルトの設定ファイルは以下なのか?
- /etc/crontab
- 実行したいユーザになって、以下のコマンドで、設定ファイルを編集する。
- 前の処理が処理中でも、次の処理が実行されてしまうので注意
cron以外にも、同様のソフトがある。
ジョブ管理システム
ジョブ管理システム - Wikipedia
たくさんのジョブを管理する場合は、ジョブとジョブの実行の順番の配慮など、cronではきびしいので、こういうミドルウェアもよく使われている。
Java
http://www.quartz-scheduler.org/documentation/quartz-2.1.x/quick-start
at
ディスク
df
du
du -h
状態確認
sysstatパッケージをあらかじめ導入しておく。
たとえば、
sudo apt-get install sysstat
システム関連のデータなので、
/proc
の値を直接見ることもできるが、コマンドをたたいたほうが、利便性がよい。