既に存在しないディレクトリでコマンドを実行したときのエラー
ターミナルで作業中に、カレントディレクトリが他プロセスにより削除された後でコマンドを打つとエラーになることがあります。
冷静にメッセージを見れば察しはつくのですが、余裕がない時に起きるとちょっとビックリする。
pwd
コマンドは削除済みのフォルダであっても特にエラーにならない
$ ls /tmp #/tmp以下にディレクトリは存在しない $ pwd /tmp/work
- ファイルやディレクトリを作成する系のコマンド
$ mkdir hoge mkdir: cannot create directory `hoge': No such file or directory $ touch hoge touch: cannot touch `hoge': No such file or directory
- psqlコマンド
$ psql
could not identify current directory: No such file or directory
could not identify current directory: No such file or directory
/usr/bin/psql: could not find own program executable
- javaコマンド
$ java version Error occurred during initialization of VM java.lang.Error: Properties init: Could not determine current working directory. at java.lang.System.initProperties(Native Method) at java.lang.System.initializeSystemClass(System.java:1166)
- npmコマンド
npm --version path.js:1163 cwd = process.cwd(); ^ Error: ENOENT: no such file or directory, uv_cwd at Object.resolve (path.js:1163:25) at Function.Module._resolveLookupPaths (module.js:408:17) at Function.Module._resolveFilename (module.js:480:22) at Function.Module._load (module.js:437:25) at Module.require (module.js:513:17) at require (internal/module.js:11:18) at /root/.nodebrew/node/v8.1.3/lib/node_modules/npm/bin/npm-cli.js:19:21 at Object.<anonymous> (/root/.nodebrew/node/v8.1.3/lib/node_modules/npm/bin/npm-cli.js:92:3) at Module._compile (module.js:569:30) at Object.Module._extensions..js (module.js:580:10)
pg_dumpのZオプションで作ったファイルの解凍&リストアにいつも混乱する
pg_dumpコマンドに、 -Z 9
のようにZオプションを与えるとダンプファイルがgzipで圧縮できます。
$ pg_dump -f /mydb.sql -Z 9 mydb
-F
でフォーマットを指定しない場合、plain形式(要はSQLファイル)でダンプ&gzipで圧縮されるだけなんですが、なぜか私は「pg_restoreでリストアしなきゃ」という思考回路になっているようですorz
一瞬混乱した後に、gunzipして解凍しなきゃと思うのですが、今度は次の問題にハマります。
$ gunzip mydb.sql
gzip: mydb.sql: unknown suffix -- ignored
メッセージの通り、拡張子が .gz
じゃないとNGってだけなんですが、これも一瞬???となります。
別に拡張子なんてなんでも良いだろと思うのですが、、、 次からは素直に.gzで出力しよう。
こんなことでハマるのは私だけと思いますが、2度もハマったのでメモしておきました。
bashのpipefailオプション
以前から set -e
を使って、エラー時に実行を止めるシェルをよく書いてましたが、
パイプでコマンドを繋げた場合、最後のコマンドにしか効かないことを今更ながら知ったのでメモ。
例えば、以下のシェルはsl
なんてコマンドは存在しないので、そこでエラーになり止まると思いきや、、、
#!/bin/bash set -e sl | echo "パイプの最後のコマンド" echo "戻り値を確認:$?" echo "ここには来ないはず"
後続の処理が実行されてしまいました。
$ bash /tmp/sete.sh パイプの最後のコマンド /tmp/sete.sh: 行 5: sl: コマンドが見つかりません 戻り値を確認:0 ここには来ないはず
パイプの最後のechoが正常終了してるので、パイプ実行直後の$?
が0となり後続が実行されるようです。
次にset -e
の行をset -eo pipefail
に変えて実行してみます。
$ bash /tmp/sete.sh
/tmp/sete.sh: 行 5: sl: コマンドが見つかりません
パイプの最後のコマンド
今度はパイプの最後までは実行されるが、後続処理は実行されませんでした。
上記を実行直後に$?
を確認すると、コマンドが見つからない旨のエラーコード127が返っているので処理が止まるようです。
今度は、2箇所でエラーになるように絶対にヒットしないgrep detarame
を追加してみます。
sl | grep detarame | echo "パイプの最後のコマンド"
$ bash /tmp/sete.sh
パイプの最後のコマンド
/tmp/sete.sh: 行 5: sl: コマンドが見つかりません
こんどは実行直後の$?
は1だったので、最後にエラーになったgrepコマンドの戻り値がパイプの戻り値になるようです。
ヒアストリング<<<
<<<
で標準入力に価を渡せる。
echo "hoge" | command
とcommand <<< "hoge"
は等価
改行を入れることも可能
$ cat <<< 'アイウエオ カキクケコ'
ファイルを掴んでいるプロセスを調べる
lsof <ファイル名>
でファイルを使用しているプロセルを特定できる。
$ sudo lsof /var/log/messages COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rsyslogd 1055 root 3w REG 253,0 7164 100839039 /var/log/messages
実行結果の4番目のフィールドが [0-9]w
なのは書き込みモード、[0-9]u
が読み書きモードで開かれているファイル。
応用として、書き込みモードで開かれているファイルの一覧取得方法。
$ sudo lsof|awk '$4~/^[0-9][wu][a-zA-Z]*$/{print $O}'
wとuの後には以下のようなロックモードがアルファベト1文字で表示されるので正規表現にその考慮を入れています。
The mode character is followed by one of these lock characters, describing the type of lock applied to the file: N for a Solaris NFS lock of unknown type; r for read lock on part of the file; R for a read lock on the entire file; w for a write lock on part of the file; W for a write lock on the entire file; u for a read and write lock of any length; U for a lock of unknown type; x for an SCO OpenServer Xenix lock on part of the file; X for an SCO OpenServer Xenix lock on the entire file; space if there is no lock.
または、/proc/<PID>/fd/
にプロセルが使用しているファイルへのシンボリックリンクが貼られているので、ls -l
で調べる方法もある。
$ ls -l /proc/5271/fd total 0 lrwx------. 1 vagrant vagrant 64 Jan 7 15:34 0 -> /dev/pts/0 lrwx------. 1 vagrant vagrant 64 Jan 7 15:34 1 -> /dev/pts/0 lrwx------. 1 vagrant vagrant 64 Jan 7 15:34 2 -> /dev/pts/0 lrwx------. 1 vagrant vagrant 64 Jan 7 15:34 4 -> /home/vagrant/.hoge.txt.swp
CentOS7で試したけど他のOSだと少し違うかも。
awkのNF変数
awkの組み込みのNF変数には現在行のフィールド数が入っています。
$ cat /etc/redhat-release CentOS Linux release 7.3.1611 (Core) $ awk '{print NF}' /etc/redhat-release 5
これを利用して、後方からフィールドを参照できます
$ awk '{print $(NF),$(NF-1)}' /etc/redhat-release (Core) 7.3.1611
また値をセットすることで現在行のフィールド数を操作できるので、先頭の3フィールド表示するようなことも可能です。
$ awk NF=3 /etc/redhat-release CentOS Linux release