ホーム·ターミナルのコマンド

ターミナルコマンド事典

ファイル・テキスト・git・プロセス・ネットワークまで、よく使うオプションと例つきで227件

⌨️ コマンドとオプションはそのまま打つものなので訳しません。説明だけが言語に合わせて変わります。

ファイルとディレクトリ32

移したり消したり探したりするものです。聞き返してくれない命令が混ざっているので、-i を付ける癖が手を守ります。

lsディレクトリの中身を一覧します。ドットで始まる名前は -a を付けるまで出てきません。cdシェルの現在ディレクトリを移します。シェル組み込みなので、スクリプトやサブシェルの中の cd は外側のシェルを動かしません。pwd今いるディレクトリを表示します。シンボリックリンク経由で入った場合は既定でリンク側の経路が出て、実体の経路は -P だけが示します。mkdirディレクトリを作ります。-p を付けないと、親が無いときも既にあるときもエラーで止まります。rmdir空のディレクトリだけを消します。中に何かあれば拒否するので、みな rm -r に流れます。rmファイルを完全に消します。ごみ箱は無く、rm -rf に空白が一つ紛れ込むだけで意図しないものが消えます。cpファイルやディレクトリごと複写します。宛先が既にあるかどうかで、元がその名前になるか、その中に入るかが変わります。mv名前を変えるか場所を移します。-i や -n を付けないと、宛先のファイルを黙って上書きします。touchファイルの時刻を今にし、無ければ空で作ります。中身は決して触りません。catファイルを続けてそのまま出します。一気に流すので長いファイルは less が向き、cat file | grep はパイプが一本余ります。lessファイル全体を読み込まずに一画面ずつ見せます。/ で検索し q で抜けますが、more のように最後で自動的に閉じません。headファイルの先頭を表示します。複数のファイルを渡すと、-q を付けない限りファイルごとに見出し行が挟まります。tailファイルの末尾を表示し、-f で見張り続けます。ログが切り替わった後も追うには -F が必要です。findディレクトリを歩いて一つずつ条件に当てます。-name '*.log' のように引用符で囲まないと、シェルが先に展開してしまいます。locateあらかじめ作った索引を引くので即答しますが、最後の updatedb 以降にできたファイルは見えません。treeディレクトリ構造を字下げした絵として描きます。macOS や軽量な Linux イメージには既定で入っておらず、先に導入が必要です。duファイルが実際に占めるディスク容量を足します。割り当てブロックで数えるので、ファイルサイズの合計や df の値とはずれます。dfファイルシステムごとに使用量と空き容量を示します。バイトが余っていても inode が尽きて書けなくなることがあり、それは df -i でしか見えません。lnファイルに別名を付けます。-s で作るシンボリックリンクはどこでも指せますが対象が移ると切れ、相対パスはリンク自身の場所から解釈されます。statinode に書かれた内容をそのまま見せます — 大きさ、権限、所有者と三つの時刻。書式指定は GNU が -c、BSD が -f で、GNU の -f は全く別の意味です。file名前ではなく中身を見て種類を判定します。拡張子を無視するので、.jpg のはずが実は PDF だったという事故がここで見つかります。basenameパスからディレクトリ部分を取り除き、必要なら拡張子も落とします。文字列処理だけなので、そのファイルの有無は見ません。dirnameパスのディレクトリ部分だけを残します。スラッシュが無ければ答えは点一つで、basename と同じく文字列しか見ません。realpathどんなパスもシンボリックリンクと点を解いて絶対パス一つにします。macOS のものは BSD 版なので、--relative-to のような GNU のオプションはありません。rsync二つのディレクトリの差分だけを転送します。元の末尾のスラッシュは中身を指し、付けないとディレクトリが一段深く入ります。mountファイルシステムをディレクトリに接ぎます。マウント先に元からあったものは消えるのではなく隠れるだけで、外せば戻ります。umount取り付けたファイルシステムを外します。綴りに n が無く、中で開いているファイルやシェルの現在位置が残っていると busy と言って拒みます。readlinkシンボリックリンクの指す先を一段だけ表示します。-f を付ければ最後までたどり、リンクでないファイルには何も出さず失敗で終わります。mktemp誰にも当てられない名前で一時ファイルやディレクトリを作り、その経路を表示します。自分では片付けないので、終了時の trap と組ませます。sha256sumファイルの SHA-256 の指紋を出し、ダウンロードが無事かを照合させます。一致は中身が同じという証明で、配布元が信用できるという証明ではありません。truncateファイルの長さをちょうどその大きさに合わせます。伸ばすときは穴を空けるだけで領域を確保せず、縮めるときは切れた後ろを警告なしに捨てます。shred消す前に中身を上書きして復元しにくくします。ただし SSD やコピーオンライトの btrfs、APFS では古いブロックが残り得るので、結局はディスク暗号化が答えです。

テキスト処理32

パイプでつないで使うのが本来の形です。ひとつで全部やるより、三つつないだ方が短くなります。

grep文の中から模様に合う行を抜き出します。既定が基本正規表現なので、+ ? | と () は -E かバックスラッシュが要ります。sed行単位で文字列を書き換えます。その場で直す -i が GNU と BSD で違い、末尾に g が無いと各行の最初の一つだけが変わります。awk行を欄に分けて小さなプログラムを走らせます。$0 は行全体、$1 が最初の欄で、既定の区切りは空白一つではなく連続する空白です。sort行を並べ替えます。-n が無いと文字として比べるので 10 が 9 より前に来て、順序はロケールが決めるため LC_ALL=C を前に置くと固定できます。uniq隣り合って同じ行だけを一つにまとめます。離れた重複は見えないので、ほぼ必ず sort の後に使います。wc行数、語数、バイト数を数えます。-l は改行文字を数えるので、最後の行に改行が無いとその行は数えられません。cut決まった欄や文字位置を切り出します。区切りは一文字で、連続した区切りをまとめないので、空白で揃えた表は awk の仕事です。pasteファイルを横に並べてタブでつなぎます。join と違って中身を見ず、行の位置だけで対応させます。tr文字を一対一で置き換えたり削ったりします。標準入力しか読まないので、ファイル名をそのまま渡すと失敗し、< かパイプで入れる必要があります。join二つのファイルを共通の欄でつなぎます。データベースの join と同じですが、その欄で先に並べ替えていないと行が黙って落ちます。comm並べ替えた二つのファイルを比べ、左だけ、右だけ、両方の三欄で示します。並べ替えていないと結果は無意味で、オプションは欄を選ぶのではなく隠すものです。diff二つのファイルのどこが変わったかを示します。patch やコードレビューが期待する形は -u で、違いがあると終了コードが 1 になるため set -e のスクリプトはここで止まります。patchdiff を実際のファイルに当てます。-p はパッチ内の経路を何段落とすかを決め、git のパッチは a/ b/ の接頭辞があるため -p1 が必要です。tee受け取ったものをファイルにも画面にも同時に流します。root 所有のファイルに書くにはこれで、sudo cmd > file の > は自分のシェルが開くからです。xargs入ってきた行を別の命令の引数に変えて渡します。名前に空白があると壊れるので、find -print0 と xargs -0 を組ませます。echo引数をそのまま出して改行します。-e とバックスラッシュの扱いがシェルごとに違うので、確実にしたいときは printf を使います。printfC の printf と同じように書式に沿って文字列を作ります。改行は自分では付けず、引数が残っている間は書式を先頭から繰り返します。jqJSON を独自の小さな言語で絞り込み、形を変えます。既定では入っていないことが多く、文字列の引用符を外すには -r が必要です。column欄を詰めて桁を揃え、表のように見せます。連続した区切りを一つと数えるので、空のセルがある CSV は一つずつずれます。fold長い行を決めた幅で切り、本物の改行を入れます。-s が無いと語の途中で切れ、端末の見かけの折り返しとは違って中身が変わります。nl出力しながら行番号を付けます。既定では空行を数えないため編集画面の番号とずれますが、-b a を渡せば一致します。rev行ごとに文字の並びを逆さにします。行の順序を反転するのは tac で、これは一行の中の文字です。splitファイルを幾つかの断片に切ります。見出し行は最初の断片にだけ残り、名前は -d を付けない限り aa、ab と文字で続きます。csplit大きさではなく模様が現れる位置でファイルを切ります。表示される数字は断片のバイト数で、{*} は当たる限り繰り返せという意味です。expandタブ文字を空白に変えます。Makefile は本物のタブが必要なので、これを掛けるとビルドが壊れます。shuf行を無作為な順で出します。GNU coreutils なので macOS には無く、代わりの sort -R は同じ行をまとめてしまいます。tacファイルの行を最後から順に出します。GNU coreutils なので macOS では tail -r を使い、文字を逆にする rev とは別物です。stringsバイナリから文字らしく見える部分を抜き出します。文字に見えれば何でも拾うので、多くは意味ではなく偶然です。iconv文字の符号化方式を別のものに変えます。変換できないバイトに当たると -c が無い限りそこで止まり、元の符号化を自分で見分けることはできません。vimモードのある編集器で、そのまま打っても何も入りません。i で入力を始め、Esc の後に :wq で保存、:q! で破棄します。nano画面の下に操作が書かれている素朴な編集器です。^O と ^X のキャレットは文字ではなく Ctrl を意味します。base64バイトを ASCII の文字に、また元に戻します。暗号ではなく表記の変換で、復号の指定は GNU が -d、古い macOS は -D です。

git45

取り消しに何通りもあるのが混乱のもとです — ブランチの指す先を動かすのと、打ち消すコミットを積むのは別です。

git initフォルダーを新しいgitリポジトリにします。initだけではファイルは追跡されず、addとcommitが別に必要です。git cloneリモートのリポジトリを履歴ごと複製します。--depth 1で浅く取ると古いコミットや他のブランチが無く、後で--unshallowが必要になります。git configgitの設定を読み書きします。--globalを付けないと今のリポジトリにしか書かれず、新しくクローンした所には引き継がれません。git init --bare作業ツリーを持たないリポジトリを作ります。受け取る専用なので中のファイルは編集できませんが、チェックアウト中のブランチへのpushが拒否されることもありません。git add今この瞬間のファイルの中身をコミット待ちに載せます。addした後にまた直すとその修正は入らないので、もう一度addします。git commitステージに載せたものだけを一つのコミットとして記録します。-aは追跡中のファイルしか拾わないので、新しく作ったファイルは入りません。git status何がステージに載り、何がまだかを見せます。追跡外のファイルはフォルダー名にまとめられるので、一つずつ見るには-uallを付けます。git diffまだステージに載せていない変更だけを見せます。addした直後は空に見えるので、そのときは--stagedで見ます。git logコミット履歴を新しい順に見せますが、出るのは今のHEADの祖先だけで、他のブランチまで見るには--allが必要です。git showコミット一つをメッセージと差分ごと表示します。<commit>:<path>の形で書けば、作業中のファイルに触れずに昔の中身だけ取り出せます。git blame一行ごとに最後に変えたコミットを添えて見せます。整形だけのコミットが本当の作者を隠すので、-wや--ignore-revを使います。git branchブランチを並べ、作り、消します。消してもリモートには残るので、サーバー側はgit push origin --deleteが別に必要です。git checkoutブランチの移動とファイルの復元を兼ねた古い命令で、git 2.23でswitchとrestoreに分かれました。checkout -- <file>はコミットしていない修正を取り返せない形で消します。git switchブランチの移動だけを担うgit 2.23の命令です。ファイルの中身を書き戻すことはせず、それはrestoreの役目です。git restoreファイルの中身を戻すgit 2.23の命令です。既定では作業中のファイルを上書きしてコミットしていない修正が消え、--stagedならステージから外すだけです。git merge別のブランチの作業を今のブランチに取り込みます。--squashは合流の記録を残さないので、そのブランチは後からも未マージ扱いのままです。git rebase自分のコミットを別の土台の上に付け替えます。ハッシュが変わるので、他の人がすでに取得したブランチにはrebaseせずmergeを使います。git resetブランチが指すコミットを移します。--softは変更をステージに残し、--mixed(既定)はステージを外して修正はファイルに残し、--hardはその修正まで捨てて取り返せません。git revert打ち消す変更を新しいコミットとして足します。履歴を消さない点がポインタを動かすresetとの違いで、すでにpushしたものはrevertで戻します。git cherry-pick他のブランチのコミット一つを今のブランチへ複製します。新しいハッシュになるため、後でそのブランチをmergeすると同じ変更が二度現れることがあります。git stash途中の変更を一時的にしまい、きれいな状態に戻します。既定では追跡外のファイルが残るので-uを付け、popは取り出して一覧から消し、applyは残します。git clean追跡外のファイルを削除します。gitが控えを持っていないので戻せず、-fdxは.envのような無視ファイルまで消すため、先に-nで確かめます。git remoteリモートリポジトリの名前と場所を扱います。記録するだけなので、addやset-urlをしてもfetchやpushをするまで何も行き来しません。git fetchリモートの新しいコミットを受け取るだけで、自分のファイルやブランチは動きません。反映にはmergeやrebaseが必要で、サーバーで消えたブランチは--pruneまで残ります。git pullfetchとmergeを一度に行います。だから思わぬマージコミットができるので、--rebaseや--ff-onlyで防ぎます。git push自分のコミットをリモートへ送ります。--forceはリモートのブランチを上書きして他人のコミットまで消しかねないので、リモートが動いていたら拒否する--force-with-leaseを使います。git tagコミットにバージョンのような名札を付けます。git pushだけではタグは送られないので、タグ名を指定して別に押します。git rmファイルを索引とディスクの両方から消します。--cachedはファイルを残して追跡だけ止めますが、過去の中身は履歴に残るので漏れた秘密は消えません。git mvファイルを移動して、その事実をそのままステージに載せます。gitは改名を保存せず内容の似かたから推測するので、大文字小文字だけ変える改名はmacOSやWindowsで-fが必要です。git ls-filesディスクではなく索引に入っている経路を並べます。スクリプトで追跡ファイルを回すのに確実な一覧で、-iは単独では使えず-cか-oと--exclude-standardが要ります。git update-index索引を直接いじります。この印はローカル限りでpushされず、追跡中の設定ファイルに自分の変更を残したいときは--assume-unchangedではなく--skip-worktreeです。git sparse-checkoutgit 2.25で入った命令で、大きなリポジトリのうち指定したフォルダーだけをディスクに置きます。履歴は丸ごとあり、coneモードはグロブではなくフォルダー名を取ります。git reflogHEADとブランチが通ってきた位置を記録します。reset --hardやブランチ削除で失ったコミットはここで見つかりますが、既定で90日で期限切れになり、この記録は自分の手元にしかありません。git bisectコミットの範囲を半分ずつ絞り、問題が最初に入ったコミットを見つけます。終わったらgit bisect resetが必要で、忘れるとブランチのないコミットに留まったままになります。git describe最も近いタグを起点に、今のコミットをv1.2.0-5-gabc1234のように名づけます。既定では注釈付きタグしか見ないので軽量タグには--tags、タグが無いリポジトリには--alwaysが必要です。git rev-parseHEADやv1.2.0^といった名前を実際のハッシュに解き、リポジトリの場所も教えます。スクリプトでブランチ名を得るには--abbrev-ref HEADを使い、リポジトリの外では失敗で終わります。git fsckオブジェクトデータベースを検査し、誰も指していないコミットを教えます。reflogの記録が消えた後に失った作業を探す二番目の手段で、報告はしますが修復はしません。git gc散らばったオブジェクトをまとめ、誰も使わないものを捨てて.gitを小さくします。--prune=nowはreflogが抱えていたコミットまで捨てるので、resetを取り消す安全網が無くなります。git archiveあるコミット時点のファイルをtarやzipとして書き出します。.gitや追跡外のファイルが入らないので、フォルダーをそのまま圧縮するより綺麗な配布物になります。git applydiffファイルを今の作業ツリーに当てます。コミットを作らず、パッチに書かれた作者も読まないので、メールで届いたパッチはamで当てるのが筋です。git amメールで届いたパッチを、元の作者とメッセージのままコミットにします。途中で失敗するとそこで止まるので、--continue・--skip・--abortで決着させます。git format-patchコミットごとにメール形式の.patchファイルを一つ書き出します。format-patch mainはmain自身ではなく、main以降のコミットを指します。git shortlogコミットを人ごとにまとめて数えます。同じ人がメールアドレスを二つ使っていると、.mailmapでまとめない限り二人として数えられます。git worktree同じリポジトリから二つ目の作業フォルダーを取り出し、クローンし直さずに二つのブランチを並行して扱えます。同じブランチを二か所にチェックアウトはできず、フォルダーを手で消すとpruneまで一覧に残ります。git submodule別のリポジトリをコミット一つに固定して自分のリポジトリ内に置きます。普通にクローンするとフォルダーは空で、update --initが必要ですし、親が押さえているのはブランチではなくコミットです。

プロセスとシステム36

何が動いていて何が資源を食っているかを見ます。止める前に何なのかを確かめるのが順番です。

psいま動いているプロセスを一度だけ写し取ります。`ps aux` はダッシュのない BSD 形式、`ps -ef` は POSIX 形式で、この二つを混ぜるのがよくある間違いです。topプロセス一覧を数秒ごとに描き直します。オプションが Linux と macOS でまったく違い、一回だけ取るなら Linux は `-b -n 1`、macOS は `-l 1` です。htoptop を色とマウス操作で作り直したもので、F9 でそのままシグナルを送れますが、既定では入っていないので先に `apt install htop` か `brew install htop` が必要です。killPID にシグナルを送ってプロセスを終わらせます。既定の TERM は片付ける余裕を与えますが、`-9` は捕まえられないため、開いたファイルやロックファイルが残ります。killallPID ではなく名前でプロセスをまとめて終わらせます。実行ファイル名と厳密に一致する必要があるため、`killall chrome` は "Google Chrome" を取りこぼします。pkillパターンに一致するプロセスをすべて終わらせます。`-f` を付けないとコマンド名だけを見るうえ、広すぎるパターンは思わぬものまで殺すので、同じパターンで先に pgrep を試します。pgreppkill とまったく同じ規則で、一致するプロセスの PID だけを表示します。だから何かを殺す前の下見にちょうど向いています。jobsこのシェルが起こしたバックグラウンドのジョブだけに番号を付けて示すシェル組み込みで、別の端末のジョブは出てこず、指すときは PID ではなく `%1` の形を使います。bgCtrl+Z で止めたジョブをバックグラウンドで再開します。まだこのシェルに属しているので、端末を閉じると一緒に終わります(残すなら nohup か disown)。fgバックグラウンドや停止中のジョブを手前に引き戻します。このシェルのジョブにしか効かず、指定は PID ではなく `%1` のようなジョブ番号です。nohupHUP シグナルを無視させて、ログアウト後もコマンドが生き続けるようにします。バックグラウンドには回してくれないので `&` は自分で付け、出力は静かに ./nohup.out にたまります。niceCPU の優先度を下げてコマンドを始めます。値は 19(最も譲る)から -20(最も欲張り)までで、負の値は root だけ、効くのはディスクではなく CPU だけです(ディスクは ionice)。reniceすでに動いているプロセスの優先度を変えます。一般利用者は譲る方向にしか動かせず、下げた分を戻すには root が必要です。systemctlsystemd のサービスを起こし、止め、状態を見ます。`enable` は起動時の設定だけなので今も動かすなら `enable --now`、ユニットファイルを直したあとは `daemon-reload` が必要です。journalctlsystemd がバイナリ形式でためたログを読みます。/var/log/journal がなければ再起動でログは消え、`-u` にはユニット名を正確に書く必要があります。serviceSysV 時代から残る薄い外皮で、systemd の機械では単に systemctl へ渡すだけ、理解する語も少なめです。crontab利用者ごとの定期実行表を扱います。cron は PATH がほぼ空でログイン設定も読まないため絶対パスで書く必要があり、`crontab -r` は確認なしで表を丸ごと消します。at指定した時刻に一度だけコマンドを実行します。atd デーモンが動いている必要があり(最近の配布物では入ってさえいないことも)、出力は画面ではなくメールに届きます。uptime機械が動いていた時間と負荷平均を一行で示します。三つの数字は 1・5・15 分間に実行を待ったプロセスの平均で、百分率ではないため、4 コアで 4.00 なら満杯です。freeLinux でメモリとスワップの残りを数えます。見るべき列は free ではなく available です(キャッシュは必要になれば返されるため)。macOS には無く、vm_stat を使います。vmstatメモリ・スワップ・ディスク・CPU の統計を一定間隔で出し続けます。最初の行はいまではなく起動以来の平均なので必ず捨て、si/so と wa の列から見ます。iostatディスクごとの読み書き量と待ち時間を示します。最初の一組は起動以来の平均で、Linux では sysstat の導入が必要、macOS は `-w 1 -c 5` のようにオプションが違います。lsblkディスクとその中の分割を木の形で並べます。分割されていない空き領域は出ません(それは fdisk や parted)。Linux 専用なので macOS では `diskutil list` を使います。unameカーネルの名前と版、そして機械の種類を教えます。配布物の名前は分からないので /etc/os-release(macOS は `sw_vers`)を読む必要があり、`-o` は GNU にしかありません。hostnameこの機械の名前を表示または変更します。`hostname web01` は再起動までしか保たないので、恒久化には Linux は `hostnamectl`、macOS は `scutil --set HostName` を使い、すべての IP を出す `-I` は Linux だけです。dateいまの時刻を好きな形式で表示し、日付の計算もします。`+` のあとの書式はどこでも同じですが、日付をずらすオプションは GNU が `-d`、macOS/BSD が `-v` と `-j -f` でまったく違います。env環境変数をすべて表示するか、変数を足してコマンドを一つ動かします。その変数はその一回の実行にだけ付き、シェルには何も残りません。export変数を子プロセスに引き継がせる印を付けます。このシェルを閉じると消えるので残したければ ~/.bashrc か ~/.zshrc に書き、export なしの `VAR=x` だけでは実行するプログラムから見えません。whichPATH をたどって、その名前の実行ファイルがどこにあるかを教えます。PATH しか見ないので別名・関数・シェル組み込みについては嘘をつき、正直な答えは `type -a` か `command -v` が返します。typeある名前が実際に何なのか — 別名か、関数か、組み込みか、ファイルか — をシェル自身に尋ねます。PATH しか見ない `which` が取りこぼすものが分かります。lsof開いているファイルとソケットをすべて並べ、「3000 番ポートを誰が握っているか」に答えます。sudo なしでは自分のプロセスしか見えないので、結果が空でもポートが空いている証拠にはなりません。fuserあるファイル・マウント・ポートを使っているプロセスを見つけ、望めば殺します。`-k` は SIGKILL を送って片付ける余裕を与えず、Linux(psmisc)にしかありません — macOS 版は `-cfu` だけです。watch同じコマンドを数秒ごとに走らせ直し、画面を描き替えます。パイプや `*` を含む命令は必ず引用符で囲みます(でないとシェルが watch 自身に一度だけ適用します)。macOS には既定で入っていません。timeoutコマンドに時間制限をかけ、超えたら打ち切って終了コード 124 を返します。既定のシグナルは TERM で、固まったプログラムは無視できるため `-k` で KILL を続けさせます(GNU coreutils で、macOS には入っていません)。straceプロセスがカーネルに投げるシステムコールを一つずつ表示し、どこで止まっているかを見せます。出力は stderr へ行くので `2>&1` で回し、ptrace の権限(通常は sudo)が必要で、Linux 専用です(macOS は dtruss)。dmesgカーネルが残す環状バッファを読み、ディスクや USB に何が起きたかをまず教えてくれます。大きさが決まったバッファなので古い行はすでに押し出され、最近の配布物はたいてい root を求めます(macOS は `log show`)。

ネットワーク28

つながらないとき、どこまで行けたのかを絞ります — 名前が引けないのか、経路がないのか、ポートが閉じているのか。

curlURL を一つ取ってきて本文を画面に出します。ブラウザーと違い `-L` なしでは転送を追わないので、301 が返ると空の応答のように見えます。wgetURL をファイルとして落とし、転送も自分で追います。curl は指示しなければ画面に出すのが違いで、macOS には既定で入っていません。pingICMP echo を送って相手が答えるか、どれだけかかるかを見ます。答えがなくても落ちているとは限りません — ICMP だけ捨てて TCP は通す防火壁が多いからです。traceroute目的地までに通る経路装置を一行ずつ並べます。途中に `* * *` が出ても道が切れたのではなく、その装置が答えないだけです。digDNS サーバーに直接尋ねて記録をそのまま見せます。/etc/hosts と系のキャッシュを飛ばすため、ブラウザーが見るものと違うことがあり、配布物によっては dnsutils か bind-utils の導入が必要です。nslookup名前を住所に変える古い道具で、まだ動きますが、出力の形も終了状態も一定でないため台本には向かず、いまは dig がその役を引き継いでいます。host名前を尋ねると住所とメールサーバーを二、三行で短く答えます。手早い確認には一番楽ですが、記録をすべて見るには dig が必要です。ssLinux で開いたソケットを並べる今どきの道具で、netstat の後継、接続が多い機械でずっと速いです。ただし `-p` で持ち主のプロセスを見るには root が必要です。netstatソケットと経路表を見る古い道具です。Linux では ss に座を譲り、そもそも入っていないこともあり、macOS には残っていますがソケットの持ち主のプロセスは分からないので、その答えは lsof が出します。ipLinux で住所・経路・近隣表をすべて扱う一つの命令で、ifconfig と route と arp を置き換えます。ここで変えたものは再起動で消えるため、残すには網の設定ファイルにも書きます。ifconfig網の口を見て触る古い命令です。Linux では `ip addr` が代わりを務め、そもそも入っていないこともあり、ip で足した住所をすべて出せませんが、macOS では今もこれが本物の道具です。routeカーネルの経路表を見て直す命令ですが、Linux では `ip route` に移り、BSD/macOS では `route -n get default` のように文法が別物なので、両者の例を混ぜても通りません。arp同じ構内網にいる近隣の MAC 住所をためた表を見せます。経路装置の向こう側は決してここに載らず、Linux では `ip neigh` が今の道具です。nc (netcat)TCP や UDP を素のままつないで、ポートが答えるかを見たり二台の間に管を通したりします。名前が同じで互換のない版が三つ(OpenBSD・GNU・Nmap の ncat)あり、`-z` や `-p` が無いこともあります。telnet平文の TCP 接続を開き、やり取りがそのまま回線を流れるためログインには決して使わず(それは ssh)、いま残る用途はポートが答えるかを見ることだけで、抜けるときは Ctrl+] のあと quit です。ssh別の機械に暗号化された shell を開きます。秘密鍵が他人にも読める許可なら ssh は端から拒むので `chmod 600` が必要で、ポートはここでは `-p` ですが scp と sftp では `-P` です。ssh-keygen公開鍵と秘密鍵の対を作ります。サーバーに置くのは `.pub` の側だけで、合言葉なしで作った鍵はそのファイル一つあれば誰でもそのまま入れてしまう状態です。ssh-copy-id自分の公開鍵をサーバーの ~/.ssh/authorized_keys に書き足して、合言葉を尋ねられないようにします。最初の一度は合言葉での login が開いている必要があり、`-i` には秘密鍵ではなく `.pub` を渡します。sftpssh の接続の上でファイルをやり取りする対話式の道具です。ポートは ssh の `-p` ではなく大文字の `-P` で、遠隔の shell 命令は動かせず put・get・ls など自前の命令だけを解します。scpssh に乗せてファイルを一度で複写します。ポートは大文字の `-P`、遠隔側の道にはコロンが必要で、大きい転送や繰り返す転送なら、変わっていないものを飛ばして再開できる rsync のほうが向きます。iptablesいま動いている包の濾過規則を書き換えます。規則は上から下へ見て最初に合ったものが勝つので、ACCEPT のあとに足した DROP は永遠に効かず、保存しなければ再起動で消え、22 番を開ける前に既定方針を DROP にすると遠隔の機械で自分を締め出します。ufwDebian・Ubuntu で iptables を易しい語で包んだ防火壁です。`enable` の前に SSH を開けておかないと、いま座っている接続を自分で切ってしまい、Docker はポートを iptables に直接差すため ufw の規則では塞げません。tcpdump回線を通る包をそのまま捕らえて見せます。root が必要で、何を捕らえるかはオプションではなく後ろに置く独自の絞り込み文法(`port 443 and host x`)であり、混んだ口で絞らずに捕らえると画面はたちまち埋まります。whoisドメインや IP 帯の登録情報を照会します。個人の欄はたいてい隠され、TLD ごとにサーバーが独自の形で答えるため、その出力を台本で解析するとすぐ壊れます。nmap相手の機械でどのポートが答えるかを走査します。`-sS` と `-O` は root が必要で、自分のものでない機械を走査すると相手の記録に攻撃として残り、国によっては違法なので自分の網だけに留めます。openssl s_clientTLS 接続を素で開き、証明書と握手の過程をのぞきます。`-servername` を省くと一つの住所に多くの site を置くサーバーが既定の証明書を返して「別物」が見え、`< /dev/null` を付けないと入力を待って止まったままになります。speedtest近くのサーバーと実際にやり取りして回線の速さを測ります。どの系にも既定では入っておらず、同じ名前の別物が二つ(Ookla の speedtest と Python の speedtest-cli)あってオプションが違います。mtrtraceroute と ping を一つの表にまとめて更新し続けるので、時々起きる欠落を捕らえるのに向きます。途中の跳びの損失はたいていその装置が返答を節約しているだけで、最後の跳びまで続く損失だけが本物です。

圧縮と転送14

まとめることと縮めることは別の仕事です。tar がまとめ、gzip が縮め、.tar.gz はその両方です。

tarファイルを一つの束にまとめるだけで、それ自体は圧縮しません。縮めるのは `-z`(gzip)・`-j`(bzip2)・`-J`(xz) の役目で、作る `-c`・取り出す `-x`・中身を見る `-t` のうち一つだけを先に置き、古い書き方では `-f` を最後のオプションにして、その直後に書庫名を書きます。gzipファイル一つを .gz に圧縮しますが、既定では成功した時点で元のファイルを消してしまうので、残したいときは `-k` を付けるか `-c` で標準出力に流します。複数をまとめる働きはなく、だから前に tar が来ます。gunzip.gz を展開して元のファイルに戻し、成功すると .gz の側を消すので、残すなら `-k`、同名のファイルが既にあるときは `-f` が必要で、ディスクに書かずに流したいときは `-c`(zcat と同じ)を使います。ziptar と違って圧縮まで自前で行い、Windows が何も入れずに開けるのはこの形式です。ディレクトリを入れるには `-r` が必要で、付けないと入れ物だけが入って中身は空、`-e` で掛ける錠は古い ZipCrypto なので弱いままです。unzip.zip を展開しますが、`-d` を与えないと今いるディレクトリにそのままぶちまけるので、先に `-l` で最上位のフォルダーがあるかを見ます。古い Windows で作られたものは名前が化けるため `-O CP932` が要り、`-P` で渡した合言葉はシェルの履歴と ps に残ります。bzip2gzip より時間はかかりますが小さくなります。gzip と同じく元のファイルを消して .bz2 だけを残すため `-k` が要り、tar と組むときの文字は `-j`、展開は `-d`(bunzip2 と同じ)です。xzよく使う三つの中でいちばん小さくなりますが遅く、`-9` では 700 MB ほどのメモリーを使います。既定では一つの核だけで動くので `-T0` を足し、`-k` を付けないと元のファイルは消え、tar で指定する文字は大文字の `-J` です。zcat.gz の中身をディスクに展開せずそのまま標準出力へ流すので、ローテーションしたログをその場で grep できます。圧縮されていないファイルも一緒に読ませるなら `-f`、bzip2・xz・zstd には bzcat・xzcat・zstdcat が別にあります。7z最初に a(追加)・x(パスのまま展開)・e(平らに展開)・l(一覧)といった語を置いて使い、.7z だけでなく zip・tar・rar も読め、圧縮率も高いほうです。出力先は `-o` に空白を入れず続けて書き、名前まで隠すには `-p` に `-mhe=on` を添えます。ddブロックのまま丸ごと写すので、起動用のイメージを装置へ書き込むのはこれです。`of=` に書いた相手は確認もなく 0 番のブロックから上書きされ、戻す手立てはないため、Enter を押す直前に lsblk で装置名を確かめ、速さは `bs=4M`、進み具合は `status=progress`(macOS は Ctrl+T)で見ます。split大きなファイルをいくつもの断片に切ります。既定は 1000 行ずつという行数での分割なので、大きさで切るなら `-b 100M` のように書き、接頭の語を与えないと断片は xaa・xab となり、戻すのは `cat part_* > file` 一つで済みますが、それは接尾が順に並ぶからこそです。cpio何を詰めるかを標準入力から受けた名前の一覧で決める古い書庫道具で、その一覧はふつう find が作ります。`-o` が書き出し、`-i` が取り出し、`-t` が一覧、initramfs が使う可搬な形は `-H newc`、他人からもらった書庫は絶対パスに展開されないよう `--no-absolute-filenames` を添えます。zstd今どきの圧縮器で、gzip と同じ大きさを何倍も速く出し、`-19` では xz に近い小ささを xz よりずっと短い時間で出します。gzip と違って元のファイルは残し(消すなら `--rm`)、`-T0` で全コアを使い、tar からは `--zstd` で呼びます。rar専有の形式で、無料なのは取り出す側だけです。作るには有料の rar が要り、もらった .rar は `unrar x`(記録されたパスのまま)か、RARLAB から何も入れずに `7z x` で開きます。`e` はパスを平らにし、`-hp` は名前まで隠し、`-v100m` は分冊にします。

パーミッション15

数字モードと記号モードは同じものを指します。755 と u=rwx,go=rx は同じ意味です。

chmodファイルとディレクトリの権限ビットを決めます。chmod -R 755 は普通のファイルまで実行可能にしてしまうので、ファイルを触らせたくなければ大文字の X を使います。chownファイルの所有者とグループを変えます。他人に譲れるのは root だけなので、ほとんど常に sudo が要ります。chgrpファイルのグループだけを変えます。chown も :group で同じことができ、root でなければ自分が属するグループにしか変えられません。umask新しく作るファイルからどの権限ビットを引くかを決めます。与える値ではなく引く覆いなので 022 はファイル 644、ディレクトリ 755 になり、既にあるファイルには触れません。sudo命令一つを別の利用者、既定では root として実行します。sudo cmd > file の > は自分のシェルで開かれるので root 所有のファイルでは失敗し、そこでは tee を使います。suその利用者自身の暗証で別の利用者になります — 自分のものを尋ねる sudo とは逆で、ダッシュを省くと自分の PATH が残り command not found の元になります。idプロセスがどの利用者とグループで動くかを表示します。id -u が 0 なら root なので、スクリプトが管理者権限を確かめる定番の手です。groups利用者がどのグループに属するかを並べます。usermod で今入れたグループは再ログインまで出てきません。一覧はセッション開始時に固まるからです。whoami今有効な利用者名を出します。ログインした名前ではないので、sudo や su の中では root と出ます。passwdログイン用の暗証を変え、そのハッシュを /etc/shadow に入れます。macOS には Linux 側の指定がほとんど無く、dscl や設定画面を使います。getfacl所有者、グループ、その他とは別に付いた権限一覧を表示します。acl パッケージを入れた Linux のもので、macOS は ls -le で独自の ACL を見せます。setfacl所有者を変えずに、特定の利用者やグループにだけ権限を足します。ACL が付くと ls の権限のあとに + が出て、mask の項目が与えた権限を黙って削ることがあります。chattrファイルシステム水準の属性を付けます。+i を掛けると root でも先に外さなければ変更できず、Linux の ext4、xfs、btrfs でしか働きません。xattrmacOS で拡張属性を読み、消します。多くは com.apple.quarantine で、アプリが壊れているという警告の正体です。Linux では getfattr と setfattr を使います。visudo/etc/sudoers を施錠と文法検査つきで編集します。そのファイルを直に書き換えて間違えると全員が sudo を使えなくなり、それを防ぐのがこの命令です。

パッケージと実行環境25

何をどこに入れるかが問題です。このプロジェクトの中か、マシン全体かを先に決めてください。

npm installpackage.jsonに書かれた依存をnode_modulesへ入れ、package-lock.jsonを更新します。npm 7からpeer依存も一緒に入り、--productionは--omit=devに置き換わりました。npm cinode_modulesを消し、package-lock.jsonに書かれた通りだけを入れます。ロックファイルを書き換えず、package.jsonと食い違えばその場で失敗するので、CIではinstallの代わりにこれを使います。npm runpackage.jsonのscriptsに書いた命令を実行します。スクリプトへ渡す引数の前には--が必要で、runなしで呼べるのはstartとtestだけです。npm initpackage.jsonを作ります。npm init <name>の形はまったく別で、create-<name>を取ってきて実行します。npxパッケージの実行ファイルを呼び出します。node_modules/.binを先に見て、無ければ一時的に取ってくるので、打ち間違いで別のパッケージを走らせないよう--noを付けます。yarn addパッケージを追加してyarn.lockを更新します。yarnだけならinstallの意味で、Yarn 2以降はyarn global addが無くなり、一度だけ使う道具はyarn dlxで走らせます。pnpm addパッケージを共有ストアに置き、node_modulesからリンクでつなぎます。ワークスペースのルートでは素のaddを拒むので、-wや--filterでどこへ入れるか示します。npm audit入っている依存に既知の脆弱性があるか教えます。fix --forceは互換を壊す上位バージョンまで上げ、開発用の深い依存の警告はどうにもならないことが多いです。npm publishパッケージをレジストリへ上げます。@scope名は既定で非公開なので--access publicが必要で、一度使ったバージョン番号は二度と使えないため、まず--dry-runで入るファイルを確かめます。node --versionPATHの先頭で見つかるnodeのバージョンを表示します。バージョン管理ツールがシェルごとに別のものを指すため、エディターの端末やCIが違う版を使うことがよくあります。nvm use今のシェルが使うNodeのバージョンを切り替えます。効くのはそのシェルだけなので、新しい端末やCIは既定値に戻り、nvmはシェル関数なのでスクリプトやMakefileからはnvm.shを先に読み込む必要があります。brew installmacOSとLinuxで、あらかじめビルドされたbottleを取って入れます。画面のあるアプリは--cask、新しい版へ上げるのはinstallではなくbrew updateとbrew upgradeの仕事です。apt-get installすでに取得済みのパッケージ一覧から選んで入れます。一覧が古いと"Unable to locate package"になるのでapt-get updateが先で、スクリプトでは人向けのaptよりapt-getが安全です。apt updateパッケージ一覧を取り直すだけです。これだけでは何も入らず上がらないのでapt upgradeが続き、作りたてのコンテナは一覧が空なのでまずこれを打ちます。dnf install有効なリポジトリから依存も解いて入れます。メタデータは自分で期限切れにするのでaptのようなupdateを別に打つ必要がなく、RHEL 8以降のyumはdnfへのリンクで、Fedora 41からはdnf5です。pacman -SArchのsyncリポジトリからパッケージを入れます。ローリングリリースなので、-Syで一覧だけ更新して入れると部分更新になりライブラリが壊れるため、必ず-Syuで一緒に上げます。pip install今有効なPythonにパッケージを入れます。pipが別のインタープリターのものである事故を避けるにはpython -m pipで呼ぶのが安全で、PEP 668以降のシステムPythonは仮想環境の外への導入を拒みます。pip freeze入っているパッケージと版を一行ずつ出し、requirements.txtに流し込めます。自分で選んだものだけでなく連れて来られた依存も並ぶので、必ずその仮想環境の中で実行します。python -m venvフォルダー一つに独立したPythonとsite-packagesを作ります。作っただけでは何も起きず、activateするか.venv/bin/pythonを直接呼ぶ必要があり、経路が中に焼き込まれるので後でフォルダー名を変えると壊れます。docker runイメージから毎回新しいコンテナを作って起動します。二度打てばコンテナが二つになり、止まったものを起こすのはdocker startで、-pが無ければホストから届かず、-vが無ければ書いたものはコンテナと一緒に消えます。docker ps今動いているコンテナだけを並べます。起動直後に落ちたものは-aを付けないと見えないので、runが何もしなかったように見えるときはここを見ます。docker buildDockerfileからイメージを作ります。末尾の点はデーモンへ送るビルドコンテキストなので、フォルダーが大きいとビルドが遅くなり(.dockerignoreで削ります)、COPYはそのコンテキスト内のファイルしか見えません。docker compose upcompose.yamlに書かれたサービスを一まとまりとして立ち上げます。ハイフン付きのdocker-composeは引退したv1で今はdocker composeプラグインであり、既にあるコンテナは--buildや--force-recreateがなければそのまま再利用されます。docker execすでに動いているコンテナの中で別のプロセスを走らせます。止まっているコンテナには使えず、軽いイメージにはbashが無いのでshで入ります。docker logsコンテナの主プロセスがstdoutとstderrに書いたものを見せます。アプリがコンテナ内のファイルにログを書いていると何も出ず、コンテナを消すとログも一緒に消えます。

読み方

  • 角括弧 [ ] は省いてよい部分です。
  • 三点 … は複数並べられるという意味です。
  • オプションは大文字小文字を区別します — -r と -R が別物のコマンドもあります。

よくある質問

Q. コマンド名を訳さないのはなぜですか。

そのまま打つものだからです。ls を訳したら、シェルが知らない名前になります。オプションも同じ理由でそのままにし、説明だけを言語に合わせています。

Q. macOS と Linux でオプションが違います。

違います。macOS は BSD 系なので GNU のオプションがないことがあります — sed -i が引数を要求したり、ps が -ef を受けなかったりします。分かれる箇所は説明にどちらかを書いてあります。

Q. 取り消せないコマンドはどう見分けますか。

説明に書いてあります。rm はゴミ箱を通らず、dd は of= を間違えるとディスクを上書きし、git reset --hard と git clean -fd はコミットしていない作業を捨てます。