シェルとコマンドライン
シェルとは
シェルは、キーボードから打ち込んだコマンド(文字の命令)を解釈してOSに伝えるプログラムです。bash や zsh が代表的で、[[Linux]] やmacOSのターミナル、WindowsのWSLで使います。
ls -la # ファイル一覧を詳細表示
cd projects/app # ディレクトリ移動
grep -r "TODO" src/ # src内からTODOを検索
初学者向けポイント
- GUIより速く、繰り返し・自動化に圧倒的に強いのが価値。同じ操作をスクリプトにして再実行できる
コマンド オプション 引数が基本形。--helpやmanでその場で調べられる- パイプ
|で「あるコマンドの出力を次のコマンドの入力へ」つなげるのがUNIX流
最初に覚えるコマンド
| コマンド | 役割 |
|---|---|
ls / cd / pwd | ファイル一覧 / 移動 / 現在地 |
cat / less | ファイルの中身を見る |
grep | テキスト検索 |
find | ファイル検索 |
curl | HTTP リクエストを送る |
ターミナル・シェル・プロンプトの違い
最初に混乱しやすいのが用語です。3つは役割が違います。
- ターミナル — 文字を表示してキー入力を受け取る「窓」。macOSのターミナル.app や Windows Terminal
- シェル — その窓の中で動き、入力を解釈して実行する「中身」。bash・zsh・fish など
- プロンプト — 入力待ちを示す
$や%の記号。これはシェルが表示している
同じターミナルのまま、中で動くシェルだけを差し替えられます。ログイン時の既定のシェルは echo $SHELL、いま動いているシェルは ps -p $$ で確認できます($SHELL は既定の設定を指すため、途中で別のシェルを起動しても変わりません)。教材どおりに打ったのに動かないときは、まずシェルの種類の違いを疑います。
パイプとリダイレクトが本体
コマンドを単体で暗記するより、つなぎ方を覚えるほうが効きます。UNIX系のコマンドは、小さな道具を組み合わせて使う前提で設計されているからです。
grep ERROR app.log | wc -l # ログ中のERROR行を数える
sort access.log | uniq -c | sort -rn # 重複を数えて多い順に並べる
./deploy.sh > deploy.log 2>&1 # 標準出力とエラー出力をまとめて記録
|(パイプ)— 左の出力をそのまま右の入力へ渡す>— 出力をファイルへ上書き保存する。追記は>>。>>のつもりで>を打ち、既存のログを消す事故が定番2>&1— エラー出力(2番)を標準出力(1番)へ合流させる。付け忘れると、いちばん知りたいエラーだけがログに残らない
つまずきポイント
| 場面 | 何が起きているか |
|---|---|
cd Documents/My Project が失敗する | 空白で引数が2つに割れる。"My Project" と引用符で囲む |
"$USER" と '$USER' で結果が違う | ダブルクォートは変数を展開し、シングルクォートは文字のまま扱う |
command not found | コマンドを探す先を並べた環境変数 PATH に、そのディレクトリが入っていない |
| 処理が終わらない | Ctrl+C で中断する。Ctrl+D は入力の終わりで、意味が違う |
いちばん怖いのは削除です。rm -rf "$DIR"/* の DIR が未設定のままだと rm -rf /* と解釈され、システム全体を消しにいきます。シェルにゴミ箱はなく rm は取り消せないので、まず同じ条件を ls で試して消える対象を目で確かめてから rm に置き換えるのが安全です。
スクリプトにして再利用する
同じ手順を2回打ったら、ファイルに保存してスクリプトにします。
#!/bin/bash
set -euo pipefail # 失敗したら即中断・未定義変数を検出・パイプ途中の失敗も拾う
cd /opt/app
git pull
npm ci
1行目の #! はシバンと呼ばれ、どのシェルで実行するかの指定です。chmod +x deploy.sh で実行権限を付ければ ./deploy.sh と打つだけで動きます([[ファイルシステムとパーミッション]])。set -euo pipefail を先頭に書く習慣は特に重要で、これが無いと途中のコマンドが失敗しても残りが走り続け、「失敗したのに成功したように見える」デプロイになります。
ここから先の地図
シェルは目的ではなく道具なので、「何をしたいか」によって次に読むものが変わります。4つの群に整理します。
リモートのサーバーを操作する
手元のPCではなく、借りたサーバーへログインして作業するのが実務の基本形です。接続の標準が [[SSH]]、ログインした先の世界そのものが [[Linux]]。そこで最初にぶつかる「権限が無くて動かない」を扱うのが [[ファイルシステムとパーミッション]]、必要なソフトの入れ方が [[Linuxパッケージ管理]] です。
動かし続ける・決まった時刻に動かす
コマンドを1回打って終わりではなく、止めずに動かす段階です。常駐サービスの起動と異常時の自動復旧は [[systemdとサービス管理]]、毎晩2時のような定時実行は [[ジョブスケジューリング(cron)]] が担います。どちらも実行される中身はシェルコマンドそのもので、「手で打つと動くのに自動実行だと動かない」という定番の罠もそこで扱います。
調べる・切り分ける
障害対応では「どこまでは正常か」を順に確かめます。繋がらないときの切り分け手順は [[ネットワーク診断コマンド]]。サーバーが1台なら grep でログを追えますが、複数台に分散すると手作業では追いきれなくなり、[[オブザーバビリティ]] の仕組みが要ります。
手作業から自動化へ進める
スクリプトができたら、次はその実行を人手から離します。コミットやプルリクエストをきっかけに自動で走らせるのが [[CI/CD]]、同じ設定を多数のサーバーへ配るのが [[Ansibleと構成管理]] です。分岐やデータ加工が増えてシェルスクリプトが読みづらくなってきたら、[[Python]] のような言語へ移す判断どきです。
関連技術とのつながり
- [[Linux]] — シェル操作の主戦場
- [[Git]] — 本来はコマンドラインツール。シェルから使うと理解が深まる
- [[CI/CD]] — パイプラインの中身はほぼシェルスクリプト
- [[SSH]] — シェルをリモートのサーバーで開くための標準手段
- [[ファイルシステムとパーミッション]] — 「動かない」の原因が権限であることは非常に多い
Q: ターミナル・シェル・プロンプトのうち、打ち込んだコマンドを解釈して実行するのはどれ?
- [ ] ターミナル
- [x] シェル
- [ ] プロンプト
解説: ターミナルは文字の表示と入力を受け取る窓、プロンプトは入力待ちを示す記号で、コマンドを解釈するのは中で動くシェル(bash や zsh)です。
Q: コマンドの実行時に `2>&1` を付ける目的はどれ?
- [ ] コマンドを2回繰り返して実行する
- [x] エラー出力を標準出力へ合流させ、まとめて記録できるようにする
- [ ] 出力を上書きではなく追記に切り替える
解説: 2番がエラー出力、1番が標準出力です。`2>&1` を付けないと、いちばん知りたいエラーだけがログに残りません。追記への切り替えは `>>` です。
Q: シェルスクリプトの先頭に `set -euo pipefail` を書かないと起きやすい問題はどれ?
- [ ] スクリプトに実行権限を付けられなくなる
- [ ] シバンの行が無視されて別のシェルで実行される
- [x] 途中のコマンドが失敗しても残りが走り続け、失敗が成功のように見える
解説: 失敗時に即中断させないと、エラーを無視したままスクリプトが最後まで完了してしまいます。実行権限は chmod +x、実行するシェルの指定はシバンの役割です。