そういう設定がされてないとsudoコマンドを実行した時にパスワードを入力しないといけません。

sudo echo 1
# Password:

普通にターミナルでそれだけ実行する程度ならそれでも特に問題ないのですが、シェルスクリプトなどで処理の流れを止めたくない時にそれはちょっと困ります。

sudo -S

そんなときは-Sまたは--stdinオプションを使います。これでパスワードが標準入力で渡すことができます。

-S, --stdin read password from standard input

例えばこんな感じです。

echo 'passwd' | sudo -S echo 1 2>/dev/null
# 1

2>/dev/nullは、sudoを実行したときのPassword:という標準エラー出力のテキストが表示されないように/dev/nullに捨てています。

リポジトリはnju33/fish-age

インストール

以下でage(読み「あげ」)をインストールします。

mkdir -p ~/.config/fish/{functions,completions}
curl -o ~/.config/fish/functions/age.fish https://raw.githubusercontent.com/nju33/fish-age/master/functions/age.fish
curl -o ~/.config/fish/completions/age.fish https://raw.githubusercontent.com/nju33/fish-age/master/completions/age.fish

ここまで終わったらfishを再読込します。

使い方

バージョンを直接書く

バージョンを書いた後に--patch,--minor,--majorのどれかを指定します。ちなみに、

  • --patchは最後の数値をインクリメント

  • --minorは真ん中の数値をインクリメント

  • --majorは最初の数値をインクリメント

するという意味になります。

age v1.2.3 --patch
# v1.2.4

age v1.2.3 --minor
# v1.3.0

age v1.2.3 --major
# v2.0.0

gitのタグからバージョンを自動取得

バージョンを記した Git タグがある場合、コマンドのバージョンを省略するとタグから最新のバージョンを取得し、指定したオプションに合わせて Bump したバージョンを表示します。

# 以下のようなタグの状態のとき
git tag
# v1.1.0
# v1.2.0
# v1.2.1
# v1.2.2
# v1.2.3

age --patch
# v1.2.4

age --minor
# v1.3.0

age --major
# v2.0.0

sed -n 2pとかすると1行目だけ取得できますが、2行目以降だけ取得したい場合はどうしたらいいだろうということでした。

結論としてはこのように実行するでした。

sed -n '2,$p'

$pというのは最後の行を指すようです。つまり2行目から最後の行というような意味になるんでしょうか。

これはpvコマンドに依存します。Mac に人は Homebrew を使って以下でインストールできます。

brew install pv

pv コマンド

pvコマンドはcatのようにファイルの内容を表示することができます。そしてそれを別コマンドでパイプ(標準入力)で渡すことで、どれだけ処理が進んだかをプログレスで表示してくれます。

MySql のリストアの進歩を表示

以下のようにするとa.dumpのリストアの進歩がどれくらいか見ることができます。

pv a.dump | mysql --defaults-extra-file=db.cnf db_name
# 400MiB 0:02:18 [2.89MiB/s] [=========================================>] 100%
関連

treeコマンドは誰かにディレクトリ・ファイル構造を見せて説明したりする時に便利なコマンドです。

コマンドの使い方を見る前に以下で現在のワーキングディレクトリをベースに適当な構造を作ります。

mkdir -p {a,b}/c
touch {a,b}/c/d.{txt,log,js,css,html}

では構造を表示してみます。ワーキングディレクトリをベースとする場合、単にtreeと実行します。

tree
# .
# ├── a
# │   └── c
# │       ├── d.css
# │       ├── d.html
# │       ├── d.js
# │       ├── d.log
# │       └── d.txt
# └── b
#     └── c
#         ├── d.css
#         ├── d.html
#         ├── d.js
#         ├── d.log
#         └── d.txt

もしa/cをベースで表示したい場合はtree a/cとコマンドの後に起きます。

tree a/c
# a/c
# ├── d.css
# ├── d.html
# ├── d.js
# ├── d.log
# └── d.txt

treeには他にフィルターのようなオプションがいくつかあります。

フィルターオプション

-P

-P <pattern>オプションを使うと、パターンにマッチしたファイル名以外は非表示にできます。

tree -P '*.js|*.css' a/c  
# a/c
# ├── d.css
# └── d.js

-I

-I <pattern>-Pの逆で、マッチしたものが非表示になります。

tree -I '*.js|*.css' a/c
# a/c
# ├── d.html
# ├── d.log
# └── d.txt

-L

-L <number>を使うと何階層目まで表示するかを確認します。

tree -L 1
# .
# ├── a
# └── b

-L 1で1階層目だけなのでabが表示されます。

プロセス置換という技を使うと、本来ファイルを指定して実行してその中身を使うようなコマンドで、直接文字列を渡すといったことができるようになります。<(...)が入力、>(...)が出力向きになります。

🤔色々と憶測ですが、僕的にはこれは戻り値がファイルのように扱えるワンライナーな関数みたいなイメージでかなと思ってます。

まずLinux 上でstat -c%N /dev/fd/*でどんな/dev/fs/*があるか見ることができます。例えばその中には'/dev/fd/0' -> '/dev/pts/9'というのがあるんですが、この時ターミナル1で、

cat /dev/fd/0

とし、ターミナル2でecho 123 > /dev/pts/9を実行するとターミナル1に123と流せるというような仕組みがあります。echo >(echo)'などと実行する時も/dev/fd/63という結果がでてくるので、どこかからの標準出力が/dev/fd/63に送られてきたりしてるんだろうなと。

これがファイルの代わりとして扱えるのは/dev/fd/63が実際にコマンドが生きてる間存在するファイルか何かなんだと思います。cat /dev/nullが使えるように、(内容が渡ってくる点だけ異なる)ファイルであるならファイルを期待する箇所におけるのはおかしくないかなと。

(⚠️この機能はshでは使えない為、bashを使う必要があります。)

例えばファイルを期待するコマンドの有名なものにcatがあります。これはcat <file-path>でそのファイルパスの内容を表示するコマンドですが、プロセス置換を使うと、

bash -c 'cat <(echo -n 123)'
# 123

<(...)の中の実行結果を表示することができます。この使い方ではechoと変わらないですが、例えばbase64コマンドなどだと少し便利さを感じられます。(これもbase64 <file-path>を期待)

bash -c 'base64 <(echo -n username:password)'
# dXNlcm5hbWU6cGFzc3dvcmQ=

またdiffなどもその類です。

bash -c 'diff <(echo aaa) <(echo abb)'
# 1c1
# < aaa
# ---
# > abb

>(...)にすると前のコマンドの結果をその中のコマンドに続けて渡すことができます。

bash -c 'echo 123 > >(cat)'
# 123

使われてるポートを調べる

localhost8000から8100までのポートを調べるには以下のように実行します。

# nc -zv  -
nc -zv localhost 8000-8100

<start>-<end>には範囲を指定し3000から4000までの範囲を調べたいなら、3000-4000のようにします。

実行すると、範囲内のポートがどうだったかログが出力され、そのポートが閉じてる場合は、

nc: connectx to localhost port 8080 (tcp) failed: Connection refused

のように出力され開いてた場合は、

found 0 associations
found 1 connections:
     1: flags=82
        outif lo0
        src ::1 port 53010
        dst ::1 port 8080
        rank info not available
        TCP aux info available

Connection to localhost port 8080 [tcp/http-alt] succeeded!

のように出力されます。

またすべてがfailedの場合、このコマンドの終了ステータスは1になり、1つでもsucceededの場合は0になります。

ポートのプロセスを終了する

上記では8080番がsucceededとなりました。そのポートの内容を終了させたい場合、まずポートを使ってるプロセスの PID を以下のように調べます。

# lsof -i:
lsof -i:8080
# COMMAND     PID  USER   FD   TYPE            DEVICE SIZE/OFF NODE NAME
# com.docke 96307 nju33   43u  IPv6 0x5e43f653a65638b      0t0  TCP *:http-alt (LISTEN)

この結果のPIDの列の番号が終了させるのに必要な番号です。後はその番号をkillコマンド実行時に渡します。

kill -9 96307

Bash などの場合は、これは一行で行えます。

kill -9 $(lsof -t -i:8080)

-tにより プロセスID だけを取得できるので上のコマンドは以下と同じになります。

kill -9 96307

tarは、アーカイブファイルを作るためのコマンドです。

アーカイブを作る為の cf オプション

アーカイブファイルは-cfオプションの指定で作れます。それぞれ以下の意味があります。

  1. -c 新たにアーカイブファイルを作ります

  2. -f ファイル名は...です。

-fは値を取るオプションで、これに渡したファイル名でアーカイブファイルが作られます。ファイル名には.tarという拡張子を付けることが一般的です。

以下は作成例です。

tar -cf document.tar document

最後にアーカイブに含めたいディレクトリやファイルを続けます。これは複数指定でき、その場合はdocument html foo.ymlのように渡します。

アーカイブの中身を確認する為の tf オプション

上記セクションで作成したdocument.tarにちゃんと特定のファイルが含まれてるか確認したい場合は、-tfを使います。さらに-vを追加するとlsの結果ような形で一覧できます。

  1. -t アーカイブファイルを一覧する

  2. -v 詳しく表示

以下は確認例です。

tar -tf document.tar
# document/
# document/1.md

アーカイブに含めるファイルを絞る

「しまった、アレ含ませたくなかった!」なんて場合は--excludeオプションで含ませたくないディレクトリやファイルのパターンを渡します。

tar -f document.tar --exclude document/1.md

tar -tf document.tar
# document/

複数のパターンがある場合は、その数だけ--excludeを指定する必要があります。

tar -cf archive.tar --exclude .git/ --exclude .DS_Store .

tar tf archive.tar
# .git/ と .DS_Store を除いた現在のディレクトリ以下の
# すべてのディレクトリとファイル

アーカイブにファイルを追加する rf オプション

「しまった、アレ指定し忘れた!」なんて場合は-rfで後から追加できます。

  1. -r アーカイブに指定ディレクトリやファイルを追加

以下は追加例です。

mkdir html
touch html/1.html

tar -rf document.tar html

tar -tf document.tar
# document/
# document/1.md
# html/
# html/1.html

ちなみに作り直しても大丈夫です。

圧縮アーカイブファイルを czf, cjf オプション

targzipbzip2による圧縮を行えます。これらを使ったアーカイブファイルの拡張子は一般的にそれぞれtar.gztar.bz2になります。

オプションに出てきたzjはそれぞれ以下のような意味です。

  1. -z gzipで圧縮する

  2. -j bzip2で圧縮する

以下例です。

# gzip で
tar czf document.tar.gz document

# bzip2 で
tar cjf document.tar.bz2 document

違いはbzip2の方がアーカイブファイルサイズを小さくできますが、圧縮時間も倍以上掛かるようです。

アーカイブを展開する為の xf オプション

上記セクションで作成したdocument.tarに展開したい場合は、-xfを使います。

  1. -x アーカイブファイルからファイルを取り出す

tar -xf document.tar

後にアーカイブ内のあるファイルへのファイルパスを指定することで、それだけを取り出す事もできます。

tar -xf document.tar document/1.md

find document
# document
# document/1.md

取り出すのでは無く中身だけ見る

-xOfとして渡すことで、取り出すさずその中身を見れます。

tar -xOf document.tar document/1.md
# 1.md の中身

オプションについて

tarコマンドでは最初の短いオプション(cfなど)の塊に限って-を省略できます。つまり-cf-tfの代わりにcftfと使うことができます。

tar cf document.tar document
tar tf document.tar
tar xf document.tar document

.zip拡張子は Windows などで親しまれている圧縮形式です。また.zipで提出を期待されるような Web サービスも多いです。

圧縮

.zip拡張子のファイルを作成するにはzipコマンドを使います。

zip archive.zip 1.txt

ディレクトリを.zip化したい場合は-rオプションを指定します。以下はdir1/ディレクトリ以下をすべて含めます。

zip archive.zip dir1

含めたいディレクトリやファイルは複数指定できます。

zip -r archive.zip dir1 dir2 file1.txt file2.txt

含めたくないファイルがある場合は、-x,--excludeオプションを一緒に使います。

# dir1/.DS_Store dir2/.DS_Store は無視
zip -r archive.zip dir1 dir2 --exclude */.DS_Store 

一覧と解凍

unzipを使います。

-lオプションで指定.zipの中身を一覧できます。

unzip -l archive.zip
#   Length      Date    Time    Name
# ---------  ---------- -----   ----
#         0  04-19-2020 09:39   document/
#         0  04-19-2020 07:16   document/1.md

解凍したい場合は単に引数に対象の.zipへのパスを渡すだけです。

unzip archive.zip
関連

trapコマンドは「終了時」「エラー時」といったタイミングに処理したい事を設定できるコマンドです。例えば、シェルスクリプトの中で一時的ファイルを作成していて、最後にそれを忘れずに削除したいような場合に使うことがあります。

以下のコードは、「何十・何百行の処理」が終わった後にclean_files関数が呼ばれ一時的なファイルが削除される、という例です。

clean_files() {
  rm tempfile
}

trap 'clean_files' EXIT

# ...何十・何百行の処理

このEXITというのがフック対象の名前です。これには以下のものがあります。

  • EXIT シェルスクリプト終了時

  • ERR エラーキャッチ時

  • SIGHUP ターミナルの切断

  • SIGINT ctrl + c で中断された時

  • SIGTERM kill される時

などがあります。3 つ目からはkill -lで確認できるものが指定できます。

kill -l
#  1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
#  5) SIGTRAP      6) SIGABRT      7) SIGEMT       8) SIGFPE
#  9) SIGKILL     10) SIGBUS      11) SIGSEGV     12) SIGSYS
# 13) SIGPIPE     14) SIGALRM     15) SIGTERM     16) SIGURG
# 17) SIGSTOP     18) SIGTSTP     19) SIGCONT     20) SIGCHLD
# 21) SIGTTIN     22) SIGTTOU     23) SIGIO       24) SIGXCPU
# 25) SIGXFSZ     26) SIGVTALRM   27) SIGPROF     28) SIGWINCH
# 29) SIGINFO     30) SIGUSR1     31) SIGUSR2

呼ばれる順番はSIG*系の後、ERREXITの順番で呼ばれます。

トラップのリセット

「ここに到達したらトラップを解除したい」という場合、trap - <trap_name>を実行します。

trap - EXIT

ERR トラップ

ERRは実行コマンドの終了ステータスが0以外、または関数の終了ステータスが0以外の時にっ呼ばれます。

以下のようなスクリプトではerrorと 2 回表示されます。②回

trap 'echo error' ERR

return_err()   # 存在しないファイルを rm しようとする
{
 m ... || r return 1
}

# 存在しないファイルを rm しようとする
rm ...
return_err
```ややこしいですが、`ERR`トラップは`EXIT`トラップのコマンドや関数が`0`以外の終了ステータスで終わった時にも呼ばれます。以下の場合も`error`と表示されます。

```bash
f() {
  return 1
}

trap 'f' EXIT
trap 'echo error' ERR

同じ処理をするトラップ

フックしたい処理が同じならトラップを複数羅列することで、複数のタイミングで同じ処理ができます。

trap 'echo ...' SIGHUP SIGINT SIGTERM  

JavaScript で飯食べたい歴約 9 年、 純( nju33 ) によるノートサイトです。

このサイトではドリンク代や奨学金返済の為、広告などを貼らせて頂いてますがご了承ください。

Change Log