1 BashとBashスクリプト #
今日、多数のユーザが、GNOMEなどのGUI(グラフィカルユーザインタフェース)を介してコンピュータを使用しています。GUIは多くの機能を提供していますが、自動タスクを実行する際には用途は限定されています。シェルはGUIを適切に補完するものです。この章では、シェル(ここではBashシェル)のいくつかの側面について概要を説明します。
1.1 「シェル」とは何か? #
従来、Linuxシェルとは、Bash(Bourne again Shell)のことでした。この章では、Bashを「シェル」と呼びます。シェルはBashの他にもあり(ash、csh、ksh、zshなど)、異なる機能と特性を持っています。他のシェルの詳細については、YaSTで「シェル」を検索してください。
1.1.1 Bashの環境設定ファイル #
シェルは、次のようにして呼び出すことができます。
対話型ログインシェル. コンピュータへのログイン時に、
--login
オプションを使用してBashを呼び出す場合か、SSHを使用してリモートコンピュータへログインする場合に使用します。「通常の」対話型シェル. xtermやkonsole、gnome-terminalなどのコマンドラインインタフェース(CLI)ツールの起動時には、通常、この形式を使用します。
非対話型シェル. コマンドラインからシェルスクリプトを呼び出す場合に呼び出されます。
シェルによって読み込まれる設定ファイルは異なります。次のテーブルには、それぞれ、ログインシェル設定ファイルと非ログインシェル設定ファイルが示されています。
Bashは、実行されているシェルのタイプに応じて特定の順序で設定ファイルを検索します。詳細については、Bashのマニュアルページ(man 1 bash
)を参照してください。見出しINVOCATION
を検索します。
ファイル |
説明 |
---|---|
|
このファイルは変更しないでください。変更しても、次の更新で変更内容が破棄される可能性があります。 |
|
|
|
特定プログラムのシステム全体にわたる設定ファイルを含みます。 |
|
ログインシェル用のユーザ固有の設定をここに挿入します。 |
ログインシェルは、表1.2「非ログインシェル用Bash設定ファイル」に示す設定ファイルも参照します。
|
このファイルは変更しないでください。変更しても、次の更新で変更内容が破棄される可能性があります。 |
|
Bashのシステム全体にわたる変更を挿入する場合のみ、このファイルを使用します。 |
|
ユーザ固有の設定をここに挿入します。 |
また、Bashは複数のファイルを使用します。
ファイル |
説明 |
---|---|
|
入力したすべてのコマンドのリストを含みます。 |
|
ログアウト時に実行されます。 |
|
よく使用されるコマンドのユーザ定義エイリアス。エイリアスの定義の詳細については、 |
非ログインシェル#
ユーザがシステムにログインするのをブロックする特殊なシェル(/bin/false
と/sbin/nologin
)があります。ユーザがシステムにログインしようとすると、両方ともサイレントに失敗します。これはシステムユーザのセキュリティ対策として意図されたものですが、最新のLinuxオペレーティングシステムには、PAMやAppArmorなど、システムアクセスを制御するためのより効果的なツールがあります。
SUSE Linux Enterprise Serverのデフォルトでは、/bin/bash
が人間のユーザに割り当てられ、/bin/false
または/sbin/nologin
がシステムユーザに割り当てられます。歴史的な理由のため、nobody
ユーザは/bin/bash
を使用します。これは、システムユーザのデフォルトとして使用されていた最小限の特権を持つユーザであるためです。ただし、nobody
を使用することにより得られたわずかなセキュリティも、複数のシステムユーザが使用すると失われます。これを/sbin/nologin
に変更できるはずです。それをテストする最も早い方法は、変更を行い、サービスやアプリケーションを中断させていないかどうかを確認することです。
次のコマンドを使用して、/etc/passwd
で、すべてのユーザ、システム、および人間のユーザに割り当てられているシェルを一覧にします。出力は、システムのサービスおよびユーザによって異なります。
>
sort -t: -k 7 /etc/passwd | awk -F: '{print $1"\t" $7}' | column -t
tux /bin/bash
nobody /bin/bash
root /bin/bash
avahi /bin/false
chrony /bin/false
dhcpd /bin/false
dnsmasq /bin/false
ftpsecure /bin/false
lightdm /bin/false
mysql /bin/false
postfix /bin/false
rtkit /bin/false
sshd /bin/false
tftp /bin/false
unbound /bin/false
bin /sbin/nologin
daemon /sbin/nologin
ftp /sbin/nologin
lp /sbin/nologin
mail /sbin/nologin
man /sbin/nologin
nscd /sbin/nologin
polkitd /sbin/nologin
pulse /sbin/nologin
qemu /sbin/nologin
radvd /sbin/nologin
rpc /sbin/nologin
statd /sbin/nologin
svn /sbin/nologin
systemd-coredump /sbin/nologin
systemd-network /sbin/nologin
systemd-timesync /sbin/nologin
usbmux /sbin/nologin
vnc /sbin/nologin
wwwrun /sbin/nologin
messagebus /usr/bin/false
scard /usr/sbin/nologin
1.1.2 ディレクトリ構造 #
次のテーブルでは、Linuxシステムの最も重要な上位レベルディレクトリについて、短い概要を示します。それらのディレクトリおよび重要なサブディレクトリの詳細については、後続のリストを参照してください。
ディレクトリ |
目次 |
---|---|
|
ルートディレクトリ(ディレクトリツリーの開始場所)。 |
|
システム管理者および通常ユーザの両者が必要とするコマンドなどの必須バイナリファイル。通常、Bashなどのシェルも含みます。 |
|
ブートローダの静的ファイル |
|
ホスト固有のデバイスのアクセスに必要なファイル |
|
ホスト固有のシステム設定ファイル |
|
システムにアカウントを持つすべてのユーザのホームディレクトリを格納します。ただし、 |
|
必須の共有ライブラリおよびカーネルモジュール |
|
リムーバブルメディアのマウントポイント |
|
ファイルシステムを一時的にマウントするためのマウントポイント |
|
アドオンアプリケーションのソフトウェアパッケージ |
|
スーパーユーザ |
|
必須のシステムバイナリ |
|
システムで提供するサービスのデータ |
|
一時ファイルを格納するディレクトリ |
|
読み込み専用データを含む第二階層 |
|
ログファイルなどの可変データ |
|
システムにMicrosoft Windows*とLinuxの両方がインストールされる場合のみ利用可能。Windowsデータを含みます。 |
次のリストでは、さらに詳しい情報を提供し、ディレクトリに含まれるファイルおよびサブディレクトリの例を示します。
/bin
root
と他のユーザの両者が使用できる基本的なシェルコマンドを含みます。これらのコマンドには、ls
、mkdir
、cp
、mv
、rm
、およびrmdir
が含まれます。また、/bin
には、SUSE Linux Enterprise ServerのデフォルトシェルであるBashも含まれます。/boot
ブートに必要なデータ(ブートローダやカーネルのデータなど)と、その他のデータ(カーネルがユーザモードプログラムの実行を開始する前に使用)が含まれます。
/dev
ハードウェアコンポーネントを記述したデバイスファイルを格納します。
/etc
X Window Systemなどのプログラムの動作を制御するローカル設定ファイルを含みます。
/etc/init.d
サブディレクトリは、ブートプロセスで実行できるLSB initスクリプトを含みます。/home/USERNAME
システムにアカウントを持つすべてのユーザの個人データを格納します。このディレクトリ内のファイルは、その所有者またはシステム管理者しか変更できません。デフォルトでは、電子メールのディレクトリとパーソナルデスクトップの設定が、
.gconf/
や.config
などの非表示のファイルおよびディレクトリとして、ここに格納されます。注記: ネットワーク環境でのホームディレクトリネットワーク環境で作業するユーザのホームディレクトリは、
/home
以外のファイルシステム内のディレクトリにマップできます。/lib
システムのブートとルートファイルシステムでのコマンドの実行に必要な必須共有ライブラリを含みます。Windowsで共有ライブラリに相当するものは、DLLファイルです。
/media
CD-ROM、フラッシュディスク、デジタルカメラ(USBを使用する場合)など、リムーバブルメディアのマウントポイントを含みます。
/media
では、一般にシステムのハードディスク以外のあらゆるタイプのドライブが保持されます。リムーバブルメディアをシステムに挿入または接続し、マウントを完了すると、そのメディアにこのディレクトリからアクセスできます。/mnt
このディレクトリは一時的にマウントされるファイルシステムのマウントポイントを提供します。
root
はここにファイルシステムをマウントできます。/opt
サードパーティのソフトウェアのインストール用に予約されています。オプションソフトウェアや大型アドオンプログラムのパッケージをここに格納できます。
/root
root
ユーザのホームディレクトリ。root
の個人データがここに保存されます。/run
systemd
とさまざまなコンポーネントによって使用されるtmpfsディレクトリ。/var/run
は、/run
へのシンボリックリンクです。/sbin
s
で示唆されるように、このディレクトリはスーパーユーザ用のユーティリティを格納します。/sbin
には、/bin
内のバイナリとともにシステムのブート、復元、および回復に不可欠なバイナリを含みます。/srv
FTPやHTTPなど、システムによって提供されるサービスのデータを格納します。
/tmp
ファイルの一時的保管を必要とするプログラムによって使用されます。
重要: ブート時の/tmp
のクリーンアップ/tmp
に保存したデータは、システムのリブート後も残っているかは保証できません。データが残っているかどうかは、たとえば/etc/tmpfiles.d/tmp.conf
の設定によって異なります。/usr
/usr
は、ユーザとは無関係であり、UNIX system resourcesを意味する略語です。/usr
内のデータは静的な読み込み専用データです。このデータは、FHS (Filesystem Hierarchy Standard
)に準拠するホスト間で共有できます。このディレクトリは、GNOMEなどのグラフィカルデスクトップをはじめ、すべてのアプリケーションプログラムを含み、ファイルシステム内の第二階層を形成します。/usr
には、/usr/bin
、/usr/sbin
、/usr/local
、/usr/share/doc
など、いくつかのサブディレクトリが含まれます。/usr/bin
一般ユーザがアクセスできるプログラムを含みます。
/usr/sbin
修復関数など、システム管理者用に予約されたプログラムを含みます。
/usr/local
このディレクトリには、システム管理者がディストリビューションに依存しないローカルな拡張プログラムをインストールできます。
/usr/share/doc
システムのドキュメントファイルおよびリリースノートを格納します。
manual
サブディレクトリには、このマニュアルのオンラインバージョンが格納されます。複数の言語をインストールする場合は、このディレクトリに各言語のマニュアルを格納できます。packages
には、システムにインストールされたソフトウェアパッケージに含まれているドキュメントが格納されます。パッケージごとに、サブディレクトリ/usr/share/doc/packages/PACKAGENAME
が作成されます。このサブディレクトリには、多くの場合、パッケージのREADMEファイルが含まれます。例、設定ファイル、または追加スクリプトが含まれる場合もあります。HOWTOをシステムにインストールした場合は、
/usr/share/doc
にhowto
サブディレクトリも含まれます。このサブディレクトリには、Linuxソフトウェアの設定および操作に関する多数のタスクの追加ドキュメントが格納されます。/var
/usr
は静的な読み込み専用データを含みますが、/var
は、システム動作時に書き込まれる可変データ(ログファイル、スプールデータなど)のディレクトリです。/var/log/
にある重要なログファイルの概要は、表48.1「ログファイル」を参照してください。
1.2 シェルスクリプトの作成 #
シェルスクリプトは、データの収集、テキスト内のワードやフレーズの検索など、さまざまな有用なタスクの実行に便利な方法です。次の例では、小型のシェルスクリプトでテキストをプリントします。
#!/bin/sh 1 # Output the following line: 2 echo "Hello World" 3
最初の行は、このファイルがスクリプトであることを示すShebang文字( | |
2行目は、ハッシュ記号で始まるコメントです。意図を理解しにくい行にはコメントすることをお勧めします。適切にコメントすると、行の目的および機能を覚えることができます。また、他の読み手もスクリプトをより良く理解できます。コメントは開発コミュニティにおいてグッドプラクティスとみなされます。 | |
3番目の行で、組み込みコマンド |
このスクリプトを実行するには、その前にいくつかの前提条件があります。
すべてのスクリプトには(上記の例のように) Shebang行が含まれている必要があります。この行がない場合は、インタプリタを手動で呼び出す必要があります。
スクリプトの保存場所はどこでも構いません。ただし、シェルの検索先ディレクトリを保存場所にすることをお勧めします。シェルのサーチパスは、環境変数
PATH
で設定されます。標準ユーザには/usr/bin
への書き込みアクセスはありません。このため、スクリプトはユーザのディレクトリ~/bin/
に保存することを推奨します。上記の例では、名前はhello.sh
です。スクリプトには、実行可能パーミッションが必要です。次のコマンドで、パーミッションを設定してください。
>
chmod +x ~/bin/hello.sh
これらの前提条件をすべて満たしたら、次の方法でスクリプトを実行できます。
絶対パス. スクリプトは絶対パスで実行できます。この例では、
~/bin/hello.sh
です。任意の場所.
PATH
環境変数にスクリプトが存在するディレクトリが含まれている場合、スクリプトをhello.sh
で実行できます。
1.3 コマンドイベントのリダイレクト #
各コマンドは、入力または出力用として、3つのチャネルを使用できます。:
標準出力. デフォルトの出力チャネル。コマンドで何かをプリントする際には標準出力チャネルが使用されます。
標準入力. コマンドでユーザまたは他のコマンドからの入力を必要とする場合は、このチャネルが使用されます。
標準エラー. このチャネルは、エラーレポーティングに使用されます。
これらのチャネルをリダイレクトするには、次の方法を使用できます。
Command > File
コマンド出力をファイルに保存します。既存ファイルは削除されます。たとえば、
ls
コマンドの出力をlisting.txt
ファイルに書き込みます。>
ls > listing.txtCommand >> File
コマンド出力をファイルに追加します。たとえば、
ls
コマンドの出力をlisting.txt
ファイルに追加します。>
ls >> listing.txtCommand < File
ファイルを読み込み、指定されたコマンドへの入力とします。たとえば、ファイルのコンテンツを
read
コマンドで読み込み、変数に入力します。>
read a < fooCommand1 | Command2
左側のコマンドの出力を右側のコマンドの入力にします。たとえば、
cat
コマンドは、/proc/cpuinfo
ファイルの内容を出力します。この出力をgrep
で使用して、cpu
を含む行のみをフィルタします。>
cat /proc/cpuinfo | grep cpu
各チャネルには、対応するファイル記述子があります。標準入力には0(ゼロ)、標準出力には1、標準エラーには2が割り当てられています。このファイル記述子を<
文字または>
文字の前に挿入できます。たとえば、次の行では、foo
で始まるファイルを検索しますが、そのファイルを/dev/null
にリダイレクトすることでエラーメッセージを抑制します。
>
find / -name "foo*" 2>/dev/null
1.4 エイリアスの使用 #
エイリアスは、1つ以上のコマンドのショートカット定義です。エイリアスの構文は、次のとおりです。
alias NAME=DEFINITION
たとえば、次の行は、エイリアスlt
を定義しています。このエイリアスは、長いリストを出力し(-l
オプション)、そのリストを変更時刻でソートし(-t
オプション)、ソート順と逆の順序でプリントします(-r
オプション)。
>
alias lt='ls -ltr'
すべてのエイリアス定義を表示するには、alias
を使用します。unalias
で対応するエイリアス名を指定して、エイリアスを削除します。
1.5 Bashでの変数の使用 #
シェル変数は、グローバル変数またはローカル変数として使用できます。グローバル変数(つまり、環境変数)は、すべてのシェルでアクセスできます。対照的に、ローカル変数は、現在のシェルでのみアクセスできます。
すべての環境変数を表示するには、printenv
コマンドを使用します。変数の値を知る必要がある場合は、変数の名前を引数として挿入します。
>
printenv PATH
変数はグローバルでもローカルでも、echo
で表示できます。
>
echo $PATH
ローカル変数を設定するには、変数名の後に等号を入れ、その後に値を指定します。
>
PROJECT="SLED"
等号の前後にスペースを挿入しないでください。スペースを挿入すると、エラーになります。環境変数を設定するには、export
を使用します。
>
export NAME="tux"
変数を削除するには、unset
を使用します。
>
unset NAME
次の表には、シェルスクリプトで使用できる一般的な環境変数が含まれています。
|
現在のユーザのホームディレクトリ |
|
現在のホスト名 |
|
ツールをローカライズする場合、ツールは、この環境変数からの言語を使用します。英語を |
|
シェルのサーチパス。コロンで区切ったディレクトリのリスト |
|
各コマンドの前にプリントされる通常のプロンプトを指定します。 |
|
複数行コマンドの実行時にプリントされるセカンダリプロンプトを指定します。 |
|
現在の作業ディレクトリ |
|
現在のユーザ |
1.5.1 引数変数の使用 #
たとえば、スクリプトfoo.sh
は、次のように実行できます。
>
foo.sh "Tux Penguin" 2000
スクリプトに渡される引数すべてにアクセスするには、位置パラメータが必要です。これらのパラメータは、最初の引数には$1
、2つ目の引数には$2
という順序で割り当てます。パラメータは最大9つまで使用できます。スクリプト名を取得するには、$0
を使用します。
次のスクリプトfoo.sh
は、1から4までのすべての引数をプリントします。
#!/bin/sh echo \"$1\" \"$2\" \"$3\" \"$4\"
このスクリプトを既出例の引数を使用して実行すると、次の結果が出力されます。
"Tux Penguin" "2000" "" ""
1.5.2 変数置換の使用 #
変数置換では、変数のコンテンツに、左側または右側からパターンを適用します。次のリストに、可能な構文形式を示します。
${VAR#pattern}
左側から最も短い一致を削除します。
>
file=/home/tux/book/book.tar.bz2>
echo ${file#*/} home/tux/book/book.tar.bz2${VAR##pattern}
左側から最も長い一致を削除します。
>
file=/home/tux/book/book.tar.bz2>
echo ${file##*/} book.tar.bz2${VAR%pattern}
右側から最も短い一致を削除します。
>
file=/home/tux/book/book.tar.bz2>
echo ${file%.*} /home/tux/book/book.tar${VAR%%pattern}
右側から最も長い一致を削除します。
>
file=/home/tux/book/book.tar.bz2>
echo ${file%%.*} /home/tux/book/book${VAR/pattern_1/pattern_2}
VARのコンテンツをPATTERN_1からPATTERN_2に置換します。
>
file=/home/tux/book/book.tar.bz2>
echo ${file/tux/wilber} /home/wilber/book/book.tar.bz2
1.6 コマンドのグループ化と結合 #
シェルでは、条件付き実行のため、コマンドを結合し、グループ化することができます。各コマンドが返す終了コードにより、コマンドの成功または失敗が判別されます。終了コードが0(ゼロ)の場合、コマンドは成功しました。それ以外はすべて、コマンド固有のエラーをマークします。
次に、コマンドをグループ化する方法を示します。
Command1 ; Command2
コマンドをシーケンシャルに実行します。終了コードはチェックされません。次の行では、各コマンドの終了コードにかかわらず、
cat
でファイルのコンテンツを表示し、次に、ls
でファイルプロパティをプリントします。>
cat filelist.txt ; ls -l filelist.txtCommand1 && Command2
左のコマンドが成功した場合、右のコマンドを実行します(論理AND)。次の行では、ファイルのコンテンツを表示し、そのコマンドが成功した場合のみ、ファイルのプロパティをプリントします(このリストの前の項目と比較してください)。
>
cat filelist.txt && ls -l filelist.txtCommand1 || Command2
左のコマンドが失敗した場合、右のコマンドを実行します(論理OR)次の行では、
/home/tux/foo
でのディレクトリ作成に失敗した場合のみ、/home/wilber/bar
内にディレクトリを作成します。>
mkdir /home/tux/foo || mkdir /home/wilber/barfuncname(){ ... }
シェル関数を作成します。位置パラメータを使用して、関数の引数にアクセスできます。次の行では、短いメッセージをプリントする関数
hello
を定義します。>
hello() { echo "Hello $1"; }この関数は、次のように呼び出せます。
>
hello Tux結果は、次のようにプリントされます。
Hello Tux
1.7 よく使用されるフローコンストラクトの操作 #
スクリプトのフローを制御するために、シェルには、while
、if
、for
、およびcase
コンストラクトがあります。
1.7.1 if制御コマンド #
if
コマンドは、式のチェックに使用されます。たとえば、次のコードは、現在のユーザがTuxであるかどうかをテストします。
if test $USER = "tux"; then echo "Hello Tux." else echo "You are not Tux." fi
テスト式は、複雑にすることも、シンプルにすることも可能です。次の式は、ファイルfoo.txt
が存在するかどうかをチェックします。
if test -e /tmp/foo.txt ; then echo "Found foo.txt" fi
test式は、角括弧で短縮することもできます。
if [ -e /tmp/foo.txt ] ; then echo "Found foo.txt" fi
その他の役に立つ式については、https://bash.cyberciti.biz/guide/If..else..fiを参照してください。
1.7.2 for
コマンドによるループの作成 #
for
ループを使用すると、エントリのリストにコマンドを実行できます。たとえば、次のコードは、現在のディレクトリ内のPNGファイルの特定の情報をプリントします。
for i in *.png; do ls -l $i done
1.8 詳細情報 #
Bashに関する重要な情報は、マニュアルページman
bash
に記載されています。このトピックの詳細については、次のリストを参照してください。
https://tldp.org/LDP/Bash-Beginners-Guide/html/index.html—Bash Guide for Beginners
https://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html—BASH Programming - Introduction HOW-TO
https://tldp.org/LDP/abs/html/index.html—Advanced Bash-Scripting Guide
https://www.grymoire.com/Unix/Sh.html—Sh - the Bourne Shell