Ubuntuのbashスクリプト入門【作成から実行まで】

シェルスクリプト

「シェルスクリプトって難しそう」と思っていませんか?実際にやってみると、ファイルを1つ作って実行権限を付けるだけで動き始めます。本記事では Ubuntu 24.04 LTS にプリインストールされている bash 5.2.21 を使い、スクリプトの作成から実行・変数・条件分岐・ループ・関数まで、すべて docker run --rm ubuntu:24.04 で実際に動かした出力を載せながら解説します(2026-06-15 実測)。コマンド結果はすべて本物のコンテナの stdout です。

この記事のポイント

  • Ubuntu 24.04 LTS には bash 5.2.21(パッケージ 5.2.21-2ubuntu4)がデフォルトで入っており、追加インストール不要
  • スクリプトは #!/bin/bash(シバン行)で始め、chmod +x で実行権限を付与する
  • 変数・条件分岐(if)・ループ(for/while)・関数の基本構文を実行結果つきで解説
  • 終了コード $? で成否を判定(実測:成功=0、存在しないファイルの ls 失敗=2)
  • shellcheck 0.9.0SC2086SC2045 などの落とし穴を実際に検出してくれる

目次

  1. bashスクリプトとは
  2. スクリプトの作り方と実行方法
  3. 変数の使い方
  4. 条件分岐(if文)の書き方
  5. ループ(for・while)の書き方
  6. 関数の定義と呼び出し
  7. 終了コードとエラー処理
  8. shellcheckでスクリプトを検証する
  9. よくあるエラーと解決策
  10. Ubuntu バージョンによる違い
  11. まとめ

bashスクリプトとは

bash(バッシュ)は Ubuntu のデフォルトシェルです。シェルとは、入力したコマンドを解釈して OS に渡す「窓口」のプログラムのこと。通常はターミナルで 1 行ずつコマンドを打ちますが、複数のコマンドをファイルにまとめたものが「bashスクリプト」です。

たとえば「毎日ログをバックアップして、古いファイルを削除して、完了を記録する」という一連の作業を 1 つのスクリプトにまとめれば、コマンド 1 つで自動実行できます。VPS でサーバーを運用するなら、この自動化が大きな武器になります。

まず、Ubuntu 24.04 に入っている bash のバージョンを確認してみましょう。以下は docker run --rm ubuntu:24.04 で実際に実行した出力です。

bashバージョン確認(ubuntu:24.04 実測)
bashバージョン確認(ubuntu:24.04 実測)



ubuntu@linuxlab: ~ (ubuntu:24.04)
$ bash –version
GNU bash, version 5.2.21(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2022 Free Software Foundation, Inc.
$ echo $BASH_VERSION
5.2.21(1)-release
$ dpkg -l bash | grep ‘^ii’
ii bash 5.2.21-2ubuntu4 amd64 GNU Bourne Again SHell
$ which bash && ls -la $(which bash)
/usr/bin/bash
-rwxr-xr-x 1 root root 1446024 Mar 31 2024 /usr/bin/bash

Ubuntu 24.04 LTS では bash 5.2.21(パッケージ名 5.2.21-2ubuntu4)がプリインストールされていました。バイナリは /usr/bin/bash にあり、約1.4MBです。別途インストールする必要はありません

スクリプトの作り方と実行方法

①スクリプトファイルを作成する

拡張子は .sh が一般的ですが、必須ではありません。nanovim などのエディタ、あるいは cat リダイレクトで作成します。今回はコンテナ内で cat > hello.sh を使いました。中身は次の3行です。




hello.sh
#!/bin/bash
echo “Hello, World!”
echo “スクリプト実行成功”

1 行目の #!/bin/bash は「シバン行(shebang)」と呼ばれ、このファイルを bash で実行することを OS に伝えます。必ず先頭行に書いてください。スクリプトの構造をもう少し具体的に示すと、次のようなイメージです。

bashスクリプトの構造(変数・関数・条件分岐を含む例)
bashスクリプトの構造(変数・関数・条件分岐を含む例)

②実行権限を付与する

作成したファイルはデフォルトでは実行できません。chmod +x で実行権限を付与します。実測では、作成直後の hello.sh は68バイトで、chmod +x 後にパーミッションが -rwxr-xr-x へ変わりました。




ubuntu@linuxlab: ~ (ubuntu:24.04)
$ chmod +x hello.sh
$ ls -la hello.sh
-rwxr-xr-x 1 root root 68 Jun 15 02:41 hello.sh

パーミッションの先頭が -rwxr-xr-x になっていれば実行権限が付いています(x が実行を意味します)。

③スクリプトを実行する

実行方法は 2 通りあります。./hello.sh(実行権限を使う)と bash hello.sh(bash に直接読み込ませる)です。どちらも同じ結果になりました。

はじめてのbashスクリプト作成〜実行(実測)
はじめてのbashスクリプト作成〜実行(実測)



ubuntu@linuxlab: ~ (ubuntu:24.04)
$ ./hello.sh
Hello, World!
スクリプト実行成功

$ bash hello.sh
Hello, World!
スクリプト実行成功

./hello.sh は chmod で付けた実行権限を使って実行します。bash hello.sh は bash に直接読み込ませる方法で、実行権限がなくても動きます。学習用途では bash スクリプト名 が手軽です。実際にターミナルで動かすと、次のような画面になります。

Ubuntu ターミナルでbashスクリプトを実行している様子
Ubuntu ターミナルでbashスクリプトを実行している様子

注意

./hello.shPermission denied が出た場合は chmod +x hello.sh を実行してください。また、hello.sh とだけ打つと「コマンドが見つからない」エラーになります。必ず ./ を付けるか、bash hello.sh を使ってください(この挙動は後述の「よくあるエラー」で実測しています)。

変数の使い方

bash では変数に値を代入して再利用できます。代入時は = の前後にスペースを入れず、参照時は $ を頭に付けます。次の variables.sh を引数 arg1 arg2 付きで実行しました。




variables.sh
#!/bin/bash
NAME=”Ubuntu”
VERSION=24
MSG=”Linux を学ぼう”

echo “OS: $NAME $VERSION”
echo “メッセージ: $MSG”
echo “引数の数: $#”
echo “スクリプト名: $0”

ubuntu:24.04 コンテナで実際に実行した結果です。




ubuntu@linuxlab: ~ (ubuntu:24.04)
$ bash variables.sh arg1 arg2
OS: Ubuntu 24
メッセージ: Linux を学ぼう
引数の数: 2
スクリプト名: /tmp/variables.sh

$#2$0/tmp/variables.sh と表示され、引数の数とスクリプト名がきちんと取れています。よく使う特殊変数をまとめました。

変数 意味
$1$9 スクリプトに渡した引数 bash script.sh hello$1hello
$# 引数の個数 bash script.sh a b c3
$0 スクリプト名(パス) 実測では /tmp/variables.sh
$@ 全引数(各引数を個別に扱う) ループで 1 個ずつ処理するときに使う
$$ 現在のシェルのプロセスID 一時ファイル名に使うと衝突しにくい

注意:= の前後にスペースを入れない

変数への代入は NAME="Ubuntu" のように = の前後にスペースを入れないでください。NAME = "Ubuntu" と書くと bash は NAME をコマンドだと解釈し、実測では bash: NAME: command not found(終了コード 127)になりました。初心者が最もハマるポイントです。

条件分岐(if文)の書き方

bashの条件分岐は if [ 条件 ]; then 〜 fi の形で書きます。[ の後ろと ] の前には必ずスペースが必要です。次の condition.sh を実行しました。




condition.sh
#!/bin/bash
FILE=”/tmp/testfile.txt”
touch “$FILE”

if [ -f “$FILE” ]; then
echo “ファイルが存在します: $FILE”
else
echo “ファイルが存在しません”
fi

NUM=10
if [ “$NUM” -gt 5 ]; then
echo “$NUM は 5 より大きい”
fi

Ubuntu 24.04(bash 5.2.21)での実行結果です。




ubuntu@linuxlab: ~ (ubuntu:24.04)
$ bash condition.sh
ファイルが存在します: /tmp/testfile.txt
10 は 5 より大きい

よく使う条件式をまとめました。

条件式 意味
-f ファイル ファイルが存在する
-d ディレクトリ ディレクトリが存在する
-z "$変数" 変数が空文字
-n "$変数" 変数が空文字でない
"$a" = "$b" 文字列が等しい
"$a" != "$b" 文字列が等しくない
"$a" -eq "$b" 数値が等しい
"$a" -gt "$b" $a が $b より大きい
"$a" -lt "$b" $a が $b より小さい

ループ(for・while)の書き方

bash には for ループと while ループがあります。どちらも実際に動かして確認しました。

①forループ




loop.sh(forループ部分)
#!/bin/bash
for i in 1 2 3 4 5; do
echo ” ループ回数: $i”
done

②whileループ




loop.sh(whileループ部分)
COUNT=1
while [ “$COUNT” -le 3 ]; do
echo ” カウント: $COUNT”
COUNT=$((COUNT + 1))
done

ubuntu:24.04 コンテナでの実行結果(変数・条件分岐・ループをまとめて実測)です。

変数・条件分岐・ループの実行結果(実測)
変数・条件分岐・ループの実行結果(実測)



ubuntu@linuxlab: ~ (ubuntu:24.04)
$ bash loop.sh
=== for ループ ===
ループ回数: 1
ループ回数: 2
ループ回数: 3
ループ回数: 4
ループ回数: 5

=== while ループ ===
カウント: 1
カウント: 2
カウント: 3

算術演算は $((式)) で行います。COUNT=$((COUNT + 1)) は C 言語の COUNT++ に相当し、while ループのカウンタを1ずつ増やしています。

関数の定義と呼び出し

繰り返し使う処理は関数にまとめると、スクリプトがすっきりします。bash の関数は 関数名() { 〜 } で定義します。




functions.sh
#!/bin/bash

greet() {
local name=”$1″
echo “こんにちは、$name さん!”
}

add() {
local a=”$1″
local b=”$2″
echo $((a + b))
}

greet “Ubuntu”
greet “World”

result=$(add 10 20)
echo “10 + 20 = $result”

ubuntu:24.04 コンテナでの実行結果(実測)です。終了コードの確認も同じスクリプトの後で行いました。

bashスクリプト:関数と終了コードの実行結果(実測)
bashスクリプト:関数と終了コードの実行結果(実測)



ubuntu@linuxlab: ~ (ubuntu:24.04)
$ bash functions.sh
こんにちは、Ubuntu さん!
こんにちは、World さん!
10 + 20 = 30

ポイントは 2 つです。

  • local をつけることで、関数内だけで有効なローカル変数になります。付けないとスクリプト全体に影響が出ます
  • result=$(add 10 20)$() はコマンド置換といい、関数の出力(echo した値)を変数に代入できます

終了コードとエラー処理

コマンドが成功したかどうかは「終了コード($?)」で確認できます。成功は 0、失敗は 1 以上の値が返ります。実測では、存在するファイルの ls0、存在しないファイルの ls2 を返しました。




ubuntu@linuxlab: ~ (ubuntu:24.04)
$ ls /tmp/functions.sh; echo “終了コード: $?”
/tmp/functions.sh
終了コード: 0

$ ls /nonexistent 2>/dev/null; echo “終了コード(失敗): $?”
終了コード(失敗): 2

エラー時に終了コードが 1 とは限らない点に注意してください(ls は引数エラーで 2 を返します)。大事なのは「0なら成功、0以外なら失敗」という判定です。スクリプトで安全に止めたい場合は set -e が便利です。




set -e の挙動(実測比較)
$ bash noset.sh # set -e なし
cp: cannot stat ‘/tmp/nope_source.txt’: No such file or directory
この行は set -e なしだと実行される
スクリプト全体の終了コード: 0

$ bash withset.sh # 先頭に set -e
cp: cannot stat ‘/tmp/nope_source.txt’: No such file or directory
スクリプト全体の終了コード: 1

実測のとおり、set -e が無いと cp が失敗しても次の行が実行され、スクリプト全体は 0(成功)で終わってしまいます。set -e を先頭に書くと、失敗した時点で止まり全体の終了コードも 1 になります。バグの早期発見に役立つので、本番用スクリプトでは付けておくのがおすすめです。

shellcheckでスクリプトを検証する

書いたスクリプトに問題がないか確認するには shellcheck が便利です。Ubuntu 24.04 では apt で簡単にインストールできます。




ubuntu@linuxlab: ~ (ubuntu:24.04)
$ sudo apt-get install -y shellcheck
Get:1 http://archive.ubuntu.com/ubuntu noble/universe amd64 shellcheck amd64 0.9.0-1 [2845 kB]
Setting up shellcheck (0.9.0-1) …
$ shellcheck –version
ShellCheck – shell script analysis tool
version: 0.9.0

Ubuntu 24.04 では shellcheck 0.9.0(パッケージ 0.9.0-1、ダウンロードサイズ約2,845kB)が入りました。使い方はスクリプトファイルを引数に渡すだけです。試しに、クォート漏れと ls のループを含む「バグありスクリプト」に掛けてみました。

shellcheck 0.9.0 の実出力(SC2086 / SC2045 を実検出)
shellcheck 0.9.0 の実出力(SC2086 / SC2045 を実検出)



ubuntu@linuxlab: ~ (ubuntu:24.04)
$ shellcheck buggy.sh
In buggy.sh line 3:
echo Hello $name
^—^ SC2086 (info): Double quote to prevent globbing and word splitting.

In buggy.sh line 4:
for f in $(ls /tmp); do
^——–^ SC2045 (error): Iterating over ls output is fragile. Use globs.

In buggy.sh line 5:
echo $f
^– SC2086 (info): Double quote to prevent globbing and word splitting.
$ echo $?
1

実測では SC2086(変数のクォート漏れ:info)と SC2045ls の結果でループするのは壊れやすい:error)を検出し、終了コードは 1 でした。指摘どおり echo "$name" のようにクォートを付け、for f in /tmp/* のように glob へ書き換えると、警告ゼロ・終了コード0になりました。

正直、最初は shellcheck の警告を無視しがちなのですが、指摘を直すと「変数展開の落とし穴」や「クォートの付け忘れ」が事前にわかります。本番環境で動かす前に必ずかける習慣をつけましょう。

よくあるエラーと解決策

初心者がつまずくエラーを、実際にコンテナで再現しました。再現した本物のメッセージで対処法をまとめます。

エラーメッセージ(実測) 原因 解決策
Permission denied 実行権限がない状態で ./script.sh を実行 chmod +x スクリプト名.sh を実行
NAME: command not found(終了コード127) NAME = "値" のように = の前後にスペースを入れた NAME="値" とスペースなしで書く
cannot execute: required file not found(終了コード127) Windows で保存したファイルの改行コードが CRLF sed -i 's/\r//' スクリプト名.shCR を除去
syntax error near unexpected token 構文ミス(fi 忘れ、; 漏れなど) shellcheck スクリプト名.sh でエラー箇所を特定

Windows で編集したファイルの改行コードに注意(実測で分かった意外な挙動)

Windows のメモ帳などで保存したファイルは改行コードが CRLF(\r\n) になることがあります。古い解説では /bin/bash^M: bad interpreter と出ると書かれていますが、Ubuntu 24.04 の bash 5.2.21 で実際に CRLF スクリプトを実行したところ、メッセージは cannot execute: required file not found(終了コード127)でした。エラー文言は環境で変わります。判定は file スクリプト名.sh が確実です。




CRLF の判定と修正(実測)
$ file crlf.sh
crlf.sh: Bourne-Again shell script, ASCII text executable, with CRLF line terminators
$ ./crlf.sh
bash: ./crlf.sh: cannot execute: required file not found
$ sed -i ‘s/\r//’ crlf.sh && file crlf.sh
crlf.sh: Bourne-Again shell script, ASCII text executable
$ ./crlf.sh
test

Ubuntu バージョンによる違い

Ubuntu 22.04 と 24.04 で bash のバージョンは異なりますが、本記事で紹介した基本構文はどちらでも同様に動作します。実際に両方のコンテナで bash --version を実測しました。

bash バージョン比較:Ubuntu 22.04 vs 24.04(実測)
bash バージョン比較:Ubuntu 22.04 vs 24.04(実測)
Ubuntu バージョン bash バージョン(実測) パッケージ サポート期間
Ubuntu 22.04.5 LTS 5.1.16(1)-release 5.1-6ubuntu1.1 2027年4月まで標準サポート
Ubuntu 24.04.4 LTS 5.2.21(1)-release 5.2.21-2ubuntu4 2029年4月まで標準サポート(推奨)

どちらのバージョンでも本記事の内容は動作しますが、新しいサーバーを立てるなら Ubuntu 24.04 LTS を選ぶとサポート期間が長くて安心です。

まとめ

本記事では Ubuntu 24.04 LTS の bash 5.2.21 を docker run --rm ubuntu:24.04 で実際に動かし、bashスクリプトの基本を実測結果とともに解説しました。

  • #!/bin/bash のシバン行を先頭に書き、chmod +x で実行権限を付与する
  • 変数は NAME="値" で代入し、$NAME で参照する(= の前後にスペースなし。間違えると終了コード127)
  • 条件分岐は if [ 条件 ]; then 〜 fi[ の前後のスペースに注意
  • for i in ...; do 〜 donewhile [ 条件 ]; do 〜 done でループ処理
  • 関数は 関数名() { 〜 } で定義し、local でローカル変数を使う
  • 終了コード $?(0=成功、0以外=失敗)でエラーチェック。set -e で失敗時に即停止
  • shellcheck 0.9.0SC2086 / SC2045 などを実際に検出。本番前に必ずかける
著者アイコン
著者アイコン

bashスクリプトに慣れたら、次は VPS 上で定期実行(cron)と組み合わせるとさらに便利になります。自宅サーバーやクラウドで自動化を試してみてください。

本格的にサーバーを運用するなら、VPS でスクリプトを動かすのがおすすめです。VPS比較おすすめ7選【実測ベンチ】 を参考に、自分に合ったプランを選んでみてください。

コメント

タイトルとURLをコピーしました