Y's note

Web技術・プロダクトマネジメント・そして経営について

本ブログの更新を停止しており、今後は下記Noteに記載していきます。
https://note.com/yutakikuchi/

快適なUnixLifeのために覚えておきたい10のTips

  • この記事では快適なUnixLifeを送るための便利な開発環境設定とコマンドの基本的なTipsについて紹介する。
  • vim.emacsなどのeditorについて紹介するとキリがないので、また別で紹介したいと思う。

目次

  1. screen
  2. zsh
  3. find
  4. grep
  5. mkdir
  6. diff
  7. nkf
  8. perl
  9. cut,sort,uniq
  10. その他

screen

  • poderosaなどのタブ機能付きターミナルを使わなくてもscreenコマンドで複数のターミナルウィンドウを管理することが可能。
  • サーバ内部のプロセスとしてscreenを管理しているので、restartなどをしない限りscreenのデタッチで一時的終了、アタッチで元々の作業画面を呼び起こす事が可能。よって会社での作業もscreenを使っていれば前日の作業の途中から開始する事ができる。
設定
  • 必要な設定ファイルは$HOME/.screenrcとして次のような内容を書き込む。
escape ^Z^z  #control + zでscreenを操作する
hardstatus alwayslastline "%`%-w%{=b bw}%n %t%{-}%+w"  #接続しているhost名を表示する
bind s
startup_message off  # おまけ: 起動画面OFF 
autodetach on        # おまけ: 回線切断時に自動でdetach
defscrollback 1024   # おまけ: スクロールバッファ行数を増やす

bind s split #画面分割
bind i focus #画面移動
bind 1 only #一画面に戻す
bind 0 remove #画面削除
bind r eval echo Resize window”‘ command -c resize #Ctrl+trで分割した画面サイズ>>
を変更。 
bind -c resize ^] command 
bind -c resize j eval resize +1 command -c resize #j1行大きくきく
bind -c resize k eval resize -1 command -c resize #k1行小さくさく
  • 新規でsshした時に新しいscreen windowを開くように$HOME/.zshrcファイルに次の設定を入れる。(bashの人は.bashrc)
#sshコマンドで別のscreenを開く
function ssh_screen(){
 eval server=\${$#}
 screen -t $server ssh "$@"
}

if [ x$TERM = xscreen ]; then
 compctl -k _cache_hosts ssh_screen
 alias ssh=ssh_screen
fi
起動、デタッチ、アタッチ、消去
  • 起動中のscreenを確認する
$ screen -ls
  • screenを起動する
$ screen -S <screen名>
  • screenをデタッチ(停止)する
control + z + d
  • screenをアタッチ(再会)する
$ screen -r <screen名>
  • screenを消去する
$ kill -9 pid
$ screen -wipe
キーバインド
  • 初期学習コストが掛かるが、操作は毎日やっていれば慣れてしまう。Unix初学者の段階で学ぶと良いと思う。以下ではデフォルト設定を想定した一部を紹介する。(.screenrcにて背キーバインドは変更できるので自分の好みにカスタマイズすると良い。)
コマンド 解説
^Zc 新しいwindow作成
^Zn 次のwindowへ移動
^Zp 前のwindowへ移動
^Zt システムの情報を表示する
^Zn nは数字で、その番号のwindowへ移動
^Zw windowのリストを表示する
^ZS 画面を分割する
^Zk windowを閉じる
画面キャプチャ
  • screen画面のキャプチャは次のような感じ。画面下に0 zsh,1 localhostと出ているのが各screen画面で、それらを切り替えて使う。

[:]

zsh

  • 最強のshell。
  • 補完機能が十分に備わっており、例えばコマンドのタイプ中にオプションを補完してくれたり、外部サーバのディレクトリさえも補完可能。
  • 参考になるサイトは漢のzsh : http://news.mynavi.jp/column/zsh/001/index.html
設定
  • $HOME/.zshrcに次のような設定を記述する。
# 文字コードの設定
export LANG=ja_JP.UTF-8

# パスの設定
PATH=$HOME/local/bin:/sbin:/usr/local/bin:/usr/sbin:$PATH
export MANPATH=$HOME/local/bin:/sbin:/usr/local/man:/usr/share/man

#補完色の設定
export LS_COLORS='di=34:ln=35:so=32:pi=33:ex=31:bd=46;34:cd=43;34:su=41;30:sg=46;30:tw=42;30:ow=43;30'

# 関数
find-grep () { find . -type f -print | xargs grep -n --binary-files=without-match $@ }

#sshコマンドで別のscreenを開く
function ssh_screen(){
 eval server=\${$#}
 screen -t $server ssh "$@"
}
if [ x$TERM = xscreen ]; then
 compctl -k _cache_hosts ssh_screen
 alias ssh=ssh_screen
fi

# プロンプトの設定 
PROMPT='%n:%~# '

# ヒストリの設定
HISTFILE=~/.histfile
HISTSIZE=10000
SAVEHIST=10000

# 履歴ファイルに時刻を記録
setopt extended_history

# 補完するかの質問は画面を超える時にのみに行う。
LISTMAX=0

# 補完の利用設定
autoload -Uz compinit; compinit

# sudo でも補完の対象
zstyle ':completion:*:sudo:*' command-path /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin

# cdのタイミングで自動的にpushd
setopt auto_pushd 

# 複数の zsh を同時に使う時など history ファイルに上書きせず追加
setopt append_history

# 補完候補が複数ある時に、一覧表示
setopt auto_list

# 補完キー(Tab, Ctrl+I) を連打するだけで順に補完候補を自動で補完
setopt auto_menu

# カッコの対応などを自動的に補完
setopt auto_param_keys

# ディレクトリ名の補完で末尾の / を自動的に付加し、次の補完に備える
setopt auto_param_slash

# ビープ音を鳴らさないようにする
setopt NO_beep

# 直前と同じコマンドラインはヒストリに追加しない
setopt hist_ignore_dups

# 重複したヒストリは追加しない
setopt hist_ignore_all_dups

# ヒストリを呼び出してから実行する間に一旦編集できる状態になる
setopt hist_verify

# auto_list の補完候補一覧で、ls -F のようにファイルの種別をマーク表示しない
setopt NO_list_types

# コマンドラインの引数で --prefix=/usr などの = 以降でも補完できる
setopt magic_equal_subst

# ファイル名の展開でディレクトリにマッチした場合末尾に / を付加する
setopt mark_dirs

# 8 ビット目を通すようになり、日本語のファイル名を表示可能
setopt print_eight_bit

# シェルのプロセスごとに履歴を共有
setopt share_history

# Ctrl+wで、直前の/までを削除する。
WORDCHARS='*?_-.[]~=&;!#$%^(){}<>'

# ファイルリスト補完でもlsと同様に色をつける。
zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}

# cd をしたときにlsを実行する
function chpwd() { ls }

# ^で、cd ..
function cdup() {
echo
cd ..
zle reset-prompt
}
zle -N cdup
bindkey '\^' cdup

# ディレクトリ名だけで、ディレクトリの移動をする。
setopt auto_cd

# C-s, C-qを無効にする。
setopt NO_flow_control
  • shellのデフォルト設定をzshにする
$ sudo chsh -s <zshコマンドのパス> <ユーザ名>
  • .zshrcの設定を反映する
$ source $HOME/.zshrc
補完の効果
  • オプションの補完。-を入力してオプション一覧をタブで補完してくれる。
$ ls -
--author                  -- print the author of each file                                                                
--block-size              -- specify block size                                                                           
--classify            -F  -- append file type indicators                                                                  
--dereference         -L  -- list referenced file for sym link                                                            
--directory           -d  -- list directory entries instead of contents                                                   
--dired               -D  -- generate output designed for Emacs' dired mode                                               
--escape              -b  -- print octal escapes for control characters                                                   
--file-type           -p  -- append file type indicators except *                                                         
--full-time               -- list both full date and full time                                                            
--help                    -- display help information                                                                     
--hide-control-chars  -q  -- hide control chars                                                                           
--human-readable      -h  -- print sizes in human readable form                                                           
--ignore              -I  -- don't list entire matching pattern                                                           
--ignore-backups      -B  -- don't list entries ending with ~                                                             
--inode               -i  -- print file inode numbers                                                                     
--kilobytes           -k  -- use block size of 1k                                                                         
--literal             -N  -- print raw characters                                                                         
--no-group            -G  -- inhibit display of group information                                                         
--numeric-uid-gid     -n  -- numeric uid, gid                                                                             
--quote-name          -Q  -- quote names                                                                                  
--recursive           -R  -- list subdirectories recursively                                                              
--reverse             -r  -- reverse sort order                                                                           
--si                  -H  -- sizes in human readable form; powers of 1000                                                 
--size                -s  -- display size of each file in blocks                                                          
--tabsize             -T  -- specify tab size                                                                             
--time                    -- specify time to show                                                                         
--time-style              -- show times using specified style                                                             
--version                 -- display version information                                                                  
--width               -w  -- specify screen width                                                                         
-S                        -- sort by size                                                                                 
-U                        -- unsorted                                                                                     
-X                        -- sort by extension                                                                            
-c                        -- status change time                                                                           
-f                        -- unsorted, all, short list                                                                    
-t                        -- sort by modification time                                                                    
-u                        -- access time                                                                                  
-v                        -- sort by version (filename treated numerically)                                               
--dereference-command-line                                   --quoting-style                                            
--dereference-command-line-symlink-to-dir                    --show-control-chars                                       
--indicator-style                                            --sort 
  • 遷移したディレクトリ一覧を表示。cdコマンドで遷移したディレクトリ一覧を表示してくれる。
$ cd - 
4 -- /home/yuta/work
5 -- /home/yuta/work/test
6 -- /home/yuta
7 -- /home/yuta/work
8 -- /home/yuta/work/dev
  • 上記以外にも沢山補完機能が備わっているので、是非試して欲しい。

find

  • 特定の条件のディレクトリ/ファイルを検索する。-and,-or,-exec,-iname,-mtime,-regex,-typeオプションをよく利用する。またsed,xargsと組み合わせて使うとより強力なツールとなる。
使用例
  • -type:検索するファイルタイプを指定する f:ファイル、d:ディレクトリ
$ find <dir> -type f
  • -iname:検索するファイル名の小文字/大文字を無視する。
$ find <dir> -iname '検索ファイル名'
$ find <dir> -regex '正規表現ファイル名'
  • -and:複数の条件をandで指定する。
$ find <dir> -type f -and -name '検索ファイル名'
  • -or:複数の条件をorで指定する。
$ find <dir> -type f -or -name '検索ファイル名'
  • -exec:.php拡張子のファイルに対してsyntax checkをする。
$ find <dir> -name '*.php' -exec php -l {} \;
  • -mtime:ファイルの最終更新日時を見る。例は3日以内の更新ファイルをバックアップディレクトリに入れる。
$ find <dir> -mtime -3 -exec cp {} ~/work/back/ \;
$ find <dir> -name '<検索文字列>' | sed -e 's/<正規表現>/mv <後方参照><置換文字列><後方参照>/g' | sh
  • findとsedを利用してtreeコマンドを作る事が可能。これを見るとtreeコマンドも意外と簡単なんだと実感する。
$ find <dir> | sort | sed -ne 's/[^\/]*\//+--/g;s/+--+/|  +/g;s/+--+/|  +/g;s/+--|/|  |/g;p'
.
+--perl
|  +--sample.pl
+--php
|  +--encrypt.php
|  +--require.php
+--python
|  +--encode.py
+--shell
|  +--curl.sh
|  +--grep.sh
  • xargsを使って特定のファイルを全て/var/tmpに移動させる。
$ find <dir> -name \*~ -print0 | xargs -0 -I{} mv {} /var/tmp
$ find <dir> -name \*~ -print0 | xargs -0 mv -t /var/tmp

grep

  • ファイル中に含まれる文字列を検索するために利用する超必須コマンド。grepで利用するオプションは-i,-e,-v,-r,--colorが挙げられる。
  • grepと同等の機能でackというコマンドもあるので、そちらも参照してほしい。参考:ackコマンド - 上から目線 はてなブックマーク - ackコマンド - 上から目線
使用例
  • -r:特定の文字列で特定のディレクトリ以下全てを検索対象としたい。
$ grep -r '文字列' dir
  • -i:文字列の小文字/大文字を区別しない。
$ grep -ir '文字列' dir
  • -v:文字列を無視する。
$ grep -v '文字列' dir
  • --color:結果として出力する時に指定した文字列の色を変える。
$ grep --color '文字列' dir
  • -e:文字列のor検索がしたい。
$ grep -e '文字列1' -e '文字列2' dir
$ grep -E '(文字列1|文字列2)' dir
  • 文字列のand検索がしたい場合はパイプを利用する。
$ grep '文字列1' dir | grep '文字列2'
  • その他:日本語などのマルチバイト文字列を検索したい場合で、ターミナル上で文字入力が出来ない場合はvimのコマンドモードでgrepを利用すると良い。またはvimgrepを利用する。vimgrep : http://d.hatena.ne.jp/yutakikuchi/20100906/1283790887
$ vim
: !grep -ir '日本語文字列' *

mkdir

  • Unixを使っている人であれば誰もが知っているディレクトリ作成コマンド。しかし意外と知られていないのが-pオプションとグルーピングである。-pにて2階層以上のディレクトリが作成可能になる。2階層以上の複数ディレクトリに対して特定のルールに沿って新規にディレクトリを作成したいときは-pとグルーピングを用いると簡単である。下ではfor文を利用した場合と比較する。
   |--- conf
   |    |--- html
   |    |--- json
   |    |--- php
   |    |--- xml
   |--- doc
   |    |--- html
   |    |--- json
   |    |--- php
   |    |--- xml
   |--- lib
   |    |--- html
   |    |--- json
   |    |--- php
   |    |--- xml
   |--- src
   |    |--- html
   |    |--- json
   |    |--- php
   |    |--- xml
  • 上の例をfor文で書いてみる。ディレクトリがたくさんある場合はこの方法でも良いが、記述が冗長的。
#!/bin/sh
for i in conf doc lib src
do
    for j in xml html json php
    do
        mkdir -p $i/$j;
    done
done
  • 次は-p とグルーピングを利用した例。記述がすごくシンプルになる。
$ mkdir -p {conf,doc,lib,src}/{html,json,php,xml}

diff

  • ファイル内容の差分を取るコマンド。よく利用するオプションは-r, -u, -I, -exclude
  • ファイルの差分をpatchファイルとして取得し、patchを当て/外しによりファイル内容を変更する事が可能。patchはディレクトリに対しても適用可能。
使用例
  • ファイルの差分を検出。
$ diff <file1> <file2>
  • -r:対象ディレクトリ以下全てを差分取得対象とする。
$ diff -r <dir1> <dir2>
  • -u:unified diff 形式の出力をする。
$ diff -ru <dir1> <dir2> 
  • -I:正規表現にマッチした行を差分対象外とする。
$ diff -r -I '正規表現' <dir1> <dir2>
  • -exclude:該当するファイルを差分対象外とする。
$ diff -r -exclude '*.txt' <dir1> <dir2>
  • diff,grep,sedを使って差分があったファイルのみを特定のフォルダにコピー。
$ diff -r <dir1> <dir2> | grep 'diff -r' | sed 's/diff -r/cp/g' | sh
patchを作成
  • diffコマンドにてpatchファイルを作成。
$ diff -u 元のファイル 変更後のファイル > patch.txt
  • patchを当てる。
$ patch -u 元のファイル < patch.txt
  • patchを外す。
$ patch -R 元のファイル < patch.txt

nkf

  • 文字コード変換コマンドの代表的なものとしてnkfとiconvが挙げられる。
  • nkfとiconvは使い勝手と性質が異なる。nkfが日本語文字を使用しているファイルに対して適用可能という点を考えるとiconvがツールとしてより汎用性が高いととらえるべきだろうが個人的にはnkfのコマンドインタフェースが好きだ。iconvはあまり使った事が無く、ここではnkfについて紹介する。
  • nkfとはNetwork Kanji Filterの略。http://sourceforge.jp/projects/nkf/
  • よく利用するオプションは-e,-j,-g,-s-w,-x,-z4,-Lu,-Lw,--overwrite
使用例
$ nkf -g <file>
  • --overwrite:処理の変更をファイルに上書き。
$ nkf --overwrite <file>
  • -e:EUC-JPとして出力。
$ nkf -e --overwrite <file>
$ nkf -s --overwrite <file>
  • -j: JISとして出力。
$ nkf -j --overwrite <file>
  • -w: UTF-8として出力。
$ nkf -w --overwrite <file>
  • -z4:全角カタカナを半角カタカナに変換して出力。
$ nkf -z4 --overwrite <file>
  • -x:半角カタカナを全角カタカナに変換しないで出力。
$ nkf -x <file>
  • -Lu:改行をUnix形式(ラインフィールド)として出力。
$ nkf -Lu -overwrite <file>
  • -Lw:改行をwindows形式(キャリッジリターン、ラインフィールド)として出力。
$ nkf -Lw -overwrite <file>
  • その他:ファイル中にキャリッジリターンが含まれるかどうかの判定はodコマンドを利用し、'\r\n'が含まれるかを見る。
$ od -c <file>

perl

  • scriptとしてではなく、ワンライナーの文字列書き換えとして利用すると便利。
  • 正規表現を強力に使えるので、sedやtrの代わりに利用すると良い。
使用例
  • ファイルのバックアップをとって(.bakファイルを生成し)、正規表現のルールに従ってファイルの内容を置換
$ perl -pi.bak -e 's/<置換文字列>/置換後文字列/g' <file>
  • 改行コードをWindows形式(キャリッジリターン、ラインフィールド)からUnix形式(ラインフィールド)に置換
$ perl -pi.bak -e 's/\015\012/\012/g' <file>
  • スペースで区切られたファイルの0-4番目と6番目の項目を出力
$ perl -lane 'print "@F[0..4] $F[6]"' <file>
  • タブで区切られたファイルの0-4番目の項目を出力
$ perl -F '\t' -lane 'print "@F[0..4] "' <file>
  • 標準出力をURlEncode
$ echo "<Encodeしたい文字列>" | perl -MURI::Escape -ne 'print uri_escape($_)'
  • 標準出力をURIDecode
$ echo '<Decodeしたい文字列>' | perl -MURI::Escape -ne 'print uri_unescape($_)'
  • 標準出力をBase64Encode
$ echo "<Encodeしたい文字列>" | perl -MMIME::Base64 -ne 'print encode_base64($_)'
  • 標準出力をBase64Decode
$ echo "<Decodeしたい文字列>" | perl -MMIME::Base64 -ne 'print decode_base64($_)'

cut,sort,uniq

  • cut:文字列の切り出し、sort:データのsort、uniq:重複行の操作が可能なコマンド。
  • それぞれのコマンドのみも使うが、パイプを用いて結果を連結するケースが多い。
cut使用例
  • 良く利用するオプションは-b,-c,-d,-f
  • -d,-f:-dがデリミタを指定、-fで何番目の行を表示するか決定。
$ cut -d ',' -f2 <file>
  • -c:文字数で区切る。-nでマルチバイトの文字列を分割しない。
$ cut -c1-4 -n <file> 
  • -b:Byte数で区切る。-nでマルチバイトの文字列を分割しない。
$ cut -b1-4 -n <file>
sort使用例
  • 良く利用するオプションは-k,-t,-r,-n
  • -t:項目のセパレータを指定。-k:セパレートされた項目数目でsort。
$ sort -t ',' -k1 <file>
  • -n:数値を基準としてsort。
$ sort -k1 -n <file>
  • -r:降順にsort。
$ sort -r <file>
uniq使用例
  • uniqはデータがsortされている事が前提。uniqでは前後行の重複しか見ない。
  • 良く利用するオプションは-c,-d,-u
  • -c:重複行のカウント数を表示。
$ uniq -c <file>
  • -d:2回以上あるもののみ出力。
$ uniq -d <file>
  • -u:1回のみ表示される行を出力。
$ uniq -u <file>
組み合わせ使用例
  • cutで2-4行目を出力し、sortでデータを降順にsortし、uniqで重複行のカウントをして出力
$ cut -d ',' -f2-4 | sort -r | uniq -c

その他

  • 以下は簡単に説明のみする項目。
dig
  • host名とipアドレスの対応をDNSに問い合わせるコマンド。/etc/hostsに設定を追加する場合などによく使う。
  • 同じような機能のコマンドとしてnslookupがある。nslookupより結果として表示される情報量が多いのと使い勝手がよいのでdigを使っている。
  • digとはdomain information groperの略。
  • 使用例
    • サーバhost名でDNSの情報を見る。
$ dig サーバhost名
    • 引き当てるDNSサーバを指定する。
$ dig @DNSサーバ サーバhost名
$ dig -x IPアドレス
    • メールエクスチェンジ(MXレコード)を引く。
$ dig MXレコード MX
base64encode/decode
  • 標準出力のbase64encode/decodeを行う
$ echo '<base64encodeしたい文字列>' | base64 -e
$ echo '<base64decodeしたい文字列>' | base64 -d
  • ファイルのbase64encode/decodeを行う
$ base64 -e file
$ base64 -d file
容量表示
  • ディスク容量
$ df -h
  • ディレクトリ容量
$ du -sh
リンクを張る
  • lnコマンド。ディレクトリ/ファイルに対してリンクを張る事が可能。
  • ディレクトリの複雑で深い階層を参照するのが面倒なときは$HOME以下にシンボリックリンクを張っておくと良い。
$ ln -s /opt/local/Library/Frameworks/Python.framework/Versions/2.6 $HOME/python2.6
パイプ + vim
  • 標準出力された内容をvimで閲覧する。パイプを使ってvimに流してしまえばリダイレクト等が不要。
$ php batch.php | vim -
コマンドラインphp
  • 単純な処理をしたい時は-rのワンライナーで書くと便利。そこそこコード量が必要になる場合はファイルに記述して実行する方が良い。
  • -l:syntax check
$ php -l <file>
  • -r:コード解釈、実行。
$ php -r 'echo "test";'
  • -i:phpの設定情報出力。
$ php -i
  • -a:interactive mode起動。control + dで実行。
$ php -a
設定ファイル配布
  • .vimrcなどを修正した時にログインした事があるサーバに対して一斉に配布したい時に利用する。下のスクリプトをdeliverという名前でファイルに保存。
#!/bin/sh
for i in `perl -ne 'if (/([a-zA-Z0-9.-]+)/) { print "$1\n";}' ~/.ssh/known_hosts`
do
    scp ~/.zshrc $i:
done
-------------
$ deliver .vimrc
  • 上のようにshellscriptファイルとしても良いが、.zshrcなどに関数として記述すると尚良い。
function deliver() {
    for i in  `perl -ne  'if (/([a-zA-Z0-9.-]+)/) { print "$1\n";}' ~/.ssh/known_hosts`
    do  
        echo scp $PWD/$1 $i:$2
    done
}
-------------
$ deliver .vimrc
lessをvimのカラーで表示させる
  • .zshrcなどに以下の設定を追記。vimのバージョン等によりパスは適宜変更。
alias less='/usr/share/vim/vim72/macros/less.sh'