今となっては、多くの人々が GNOME のようなグラフィカルユーザインターフェイス (GUI) を使用するようになっています。 GUI は多数の機能が提供されているものの、特に自動化という側面においては、限られた用途でしか使用できません。シェルは GUI を補完する仕組みで、本章で示している bash シェルの使い方を覚えれば、より効率的に作業を進めることができるようになります。
伝統的には、 シェル といえば bash (Bourne again Shell) のことを指します。本章でもそれにならい、 「シェル」 を bash の意味で使用します。実際には bash 以外の様々なシェル (ash, csh, ksh, zsh, …) がありますが、それぞれ少しずつ機能や動作が異なることに注意してください。
シェルは下記のいずれかの方式で起動することができます:
対話的なログインシェル: マシンに対してログインした際に使用されるシェルで、 bash には --login
というパラメータが追加されます。これは、 SSH などでリモートからログインした場合にも使用されるものです。
対話的な非ログインシェル: xterm, konsole, gnome-terminal など、コマンドラインインターフェイス (CLI) ツールを通じて bash を開始した場合は、こちらのシェルになります。
非対話的な非ログインシェル: コマンドラインでシェルスクリプトを実行すると、こちらのシェルになります。
それぞれのシェルはそれぞれ別々の設定ファイルを読み込みます。下記の表では、ログインシェルの場合と非ログインシェルの場合において、それぞれ読み込まれる設定ファイルを示しています。
bash は、その起動形態によって設定ファイルの読み込み方法が変化します。詳しくは bash のマニュアルページ ( man 1 bash
) 内の 起動
( INVOCATION
) の箇所をお読みください。
ファイル |
説明 |
---|---|
|
このファイルは変更してはなりません。パッケージ側で管理されているファイルであるため、更新を行うと変更した内容が上書きされてしまいます。 |
|
|
|
特定のプログラムに対するシステム全体の設定ファイルが含まれています |
|
ログインシェルでユーザ固有の設定を行いたい場合は、こちらに記述してください |
なお、ログインシェルの場合は、 表14.2「非ログインシェルで使用する際の bash 設定ファイル」 にある設定ファイルもあわせて読み込みます。
|
このファイルは変更してはなりません。パッケージ側で管理されているファイルであるため、更新を行うと変更した内容が上書きされてしまいます。 |
|
bash のみに対して、システム全体に反映すべき設定があれば、こちらのファイルに記述してください |
|
ユーザ固有の設定を行いたい場合は、こちらに記述してください |
これらに加えて、 bash では下記のようなファイルを使用します:
ファイル |
説明 |
---|---|
|
これまでに入力したコマンドラインの履歴一覧 |
|
ログアウト時に実行するスクリプトです |
|
よく使用するコマンドに対して、別名を定義することができるファイルです。別名の定義方法について、詳しくは |
システムに対してログインを許可したくないユーザの場合は、ログインシェルとして /bin/false
もしくは /sbin/nologin
を指定すると、ログインを拒否できるようになります。いずれの場合も、ユーザがシステムにログインしようとすると、特に何もメッセージが表示されることなく終了します。これは主にシステムユーザとして作成するユーザに対して設定するためのものですが、 Linux オペレーティングシステムには PAM や AppArmor など、システムへのアクセスをより効率的に制御することのできるツールが存在していることを覚えておいてください。
openSUSE Leap の既定では、一般ユーザには /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
下記の表には、 Linux システムにおける最も重要なディレクトリ構造と、それぞれのディレクトリに対する用途の説明を記載しています。
ディレクトリ |
内容 |
---|---|
|
ルートディレクトリです。ディレクトリツリーの開始点です。 |
|
システム管理者と一般ユーザの両方で必要となる、主要なバイナリファイルが含まれるディレクトリです。 bash などのシェルもここに用意されています。 |
|
ブートローダが使用する各種のファイルがあるディレクトリです。 |
|
ホスト固有のデバイスにアクセスするためのファイルがあるディレクトリです。 |
|
ホスト固有のシステム設定ファイルがあるディレクトリです。 |
|
システムにアカウントを持つ全てのユーザに対して、ホームディレクトリが作成されるディレクトリです。ただし、 |
|
主要な共有ライブラリとカーネルモジュールがあるディレクトリです。 |
|
リムーバブルメディアのマウントポイントです。 |
|
一時的にファイルシステムをマウントするためのマウントポイントです。 |
|
アドオン製品のソフトウエアパッケージが配置されるディレクトリです。 |
|
スーパーユーザ |
|
主要なシステムバイナリが含まれるディレクトリです。 |
|
システムが提供するサービス向けのデータが含まれるディレクトリです。 |
|
一時的な (テンポラリ) ファイルが配置されるディレクトリです。 |
|
読み込み専用のデータが配置される二次構造のディレクトリです。 |
|
ログファイルなどの可変データが含まれるディレクトリです。 |
|
お使いのシステムに Microsoft Windows* と Linux が同時にインストールされている場合にのみ利用できるディレクトリです。 Windows 側のデータが含まれています。 |
下記の一覧では、より詳しい説明を行っているほか、それらのディレクトリ内に存在するファイルやサブディレクトリも例示しています:
/bin
root
と一般ユーザの両方が使用する、基本的なシェルコマンド類が含まれています。たとえば ls
, mkdir
, cp
, mv
, rm
, rmdir
などがあります。また、 /bin
ディレクトリには openSUSE Leap における既定のシェル bash も含まれています。
/boot
ブートローダやカーネルのほか、カーネルがユーザモードに切り替わる前に必要となる、各種データが含まれています。
/dev
ハードウエアコンポーネントを表す各種のデバイスファイルが含まれています。
/etc
X Window System などのプログラムを制御する際に必要となる、ローカル側の設定ファイルが含まれています。 /etc/init.d
サブディレクトリには、起動処理時に実行される LSB 初期化スクリプトが含まれています。
/home/ユーザ名
システム内にアカウントを持つ各ユーザに対して提供される、プライベートなディレクトリです。ここには各ユーザやシステムの管理者のみが変更することのできる、各種のファイルが配置されます。既定では、電子メールやデスクトップ環境の個人名設定なども、この中の隠しファイルや隠しサブディレクトリ (例: .gconf/
, .config
など) に配置されます。
ネットワーク環境で作業を行っている場合、ホームディレクトリが /home
以外のディレクトリになっている場合があります。
/lib
システムを起動したり、ルートファイルシステム内で様々なコマンドを実行したりする際に必要な、各種の共有ライブラリが含まれています。 Windows では、共有ライブラリのことを DLL ファイルと呼ばれています。
/media
CD-ROM や USB メモリ、デジタルカメラ (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
は user
ではありませんし、関係もありません。 /usr
は Unix System Resources
の略で、頻繁に書き込まれるようなものではない、固定でほぼ読み込み専用の、ホスト間で共有しうるデータやプログラムが保存されます。このディレクトリは Filesystem Hierarchy Standard
(FHS) の規格に準拠したディレクトリで、 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/パッケージ名
というサブディレクトリが作成されていて、 README ファイルやその他のサンプル、設定ファイルの例や追加のスクリプトなどが提供されます。
HOWTO についても /usr/share/doc
以下の howto
サブディレクトリ内に配置されていることがあります。ここには Linux ソフトウエアの設定や操作など、様々な作業に対する追加のドキュメンテーションが配置されます。
/var
/usr
には固定でほぼ読み込み専用のデータがありましたが、/var
にはシステムの動作中に適宜書き込みや書き換えが行われる、様々な可変 (variable
) データが含まれています。これにはたとえば、ログファイルやスプールデータなどが含まれます。 /var/log/
以下のログファイルについて、詳しくは 表21.1「ログファイル」 をお読みください。
/windows
Microsoft Windows と Linux を同じシステム内にインストールしている場合にのみ、利用できるディレクトリです。ここにはお使いのシステムにインストールされた Windows のパーティションがマウントされ、ここから読み書きができるようになっています。 Windows 側のファイルシステムに依存しますが、 FAT32 であれば何も問題なく読み書きすることができます。 NTFS の場合にも openSUSE Leap は読み書きの両方に対応する機能が用意されていますが、ドライバである NTFS-3g 側の制限により、全ての機能を利用できるというわけではありません。
シェルスクリプトは、幅広い処理を実行することができる便利な仕組みです。データの収集やファイル内の単語や語句の検索など、様々な処理を行うことができます。下記の例では、テキストを出力する簡単なシェルスクリプトを示しています:
#!/bin/sh 1 # 下記の行を出力します: 2 echo "Hello World" 3
最初の行は シェバン と呼ばれる文字列 ( | |
2 行目はハッシュ記号で始まるコメント文です。スクリプト内で何をやっているのかがわかりにくいような場合に、書いておいたほうがよいものです。適切にコメントを記述することで、各行の目的や意味を記録しておくことができます。また、自分以外の読み手に対しても、スクリプトの理解をより深めることができるようになります。開発コミュニティ内では、コメントはよりよい実践手段として認められています。 | |
3 行目は内蔵コマンド |
スクリプトを実行するにあたっては、下記の要件を満たす必要があります:
スクリプトには、上記の例のようにシェバンを書いておくべきです。シェバンが書かれていないと、実行のたびにインタプリタを手作業で指定しなければならなくなります。
スクリプトは任意の場所に保存することができますが、一般的にはシェルから見つけやすい場所においておくことをお勧めします。シェルでパスを検索する際は、 PATH
という環境変数の内容を参照します。ただし、一般ユーザは /usr/bin
に書き込むことができませんので、スクリプトはホームディレクトリ以下の ~/bin/
などに保存しておくとよいでしょう。上記のファイルは、 hello.sh
というファイル名で保存しているものとします。
スクリプトには実行のアクセス権が必要です。下記の通り実行して、実行権限を付与してください:
>
chmod +x ~/bin/hello.sh
上記の要件を全て満たしたら、あとは下記のいずれかの方式でスクリプトを実行します:
絶対パス: スクリプトは絶対パスで実行することができます。今回の例の場合は、 ~/bin/hello.sh
と入力すると、実行することができます。
任意の場所: PATH
環境変数にはスクリプトの存在しうるディレクトリが並べられています。このディレクトリ内のどこかに hello.sh
を配置していれば、 hello.sh
と入力するだけで実行することができます。
それぞれのコマンドには、入力や出力のための計 3 種類のチャンネルが用意されています:
標準出力: 既定の出力チャンネルです。コマンドが何らかの出力を行うと、それは標準出力に書き出されます。
標準入力: ユーザから、もしくは他のコマンドからの入力が必要な場合、このチャンネルを使用します。
標準エラー出力: コマンドは、エラー報告を行う際、このチャンネルを使用します。
これらのチャンネルをリダイレクト (転送) するには、下記のいずれかの方法があります:
コマンド > ファイル
コマンドの出力をファイルに保存します。ただし、既存のファイルは削除されることに注意してください。たとえば ls
コマンドの出力を listing.txt
ファイルに保存するには、下記のようにして行います:
>
ls > listing.txt
コマンド >> ファイル
コマンドの出力をファイルに追記します。たとえば ls
コマンドの出力を listing.txt
ファイルに追記するには、下記のようにして行います:
>
ls >> listing.txt
コマンド < ファイル
指定したコマンドに対して、ファイルの内容を入力として設定します。たとえば read
というコマンドを利用して、ファイルの内容を変数に取り込むには、下記のように実行します:
>
read a < foo
コマンド_1 | コマンド_2
左側のコマンドの出力を右側のコマンドの入力として使用します。たとえば cat
コマンドで /proc/cpuinfo
ファイルの内容を出力し、その出力を grep
コマンドでフィルタして、 cpu
という文字列を含む行だけを取り出すには、下記のように実行します:
>
cat /proc/cpuinfo | grep cpu
それぞれのチャンネルには ファイルディスクリプタ が割り当てられています。 0 (ゼロ) が標準入力、 1 が標準出力、 2 が標準エラー出力です。これらの数字を <
や >
の前に指定することで、それぞれの入出力を自在に扱うことができるようになります。たとえば foo
で始まるファイルを検索するものの、エラー出力については、 /dev/null
にリダイレクトしたい場合は、下記のように実行します:
>
find / -name "foo*" 2>/dev/null
別名定義は、 1 つまたは複数のコマンドのショートカットです。別名定義の書式は下記の通りです:
alias 名前=定義
たとえば下記の行を実行すると、 lt
という名前で、長い形式の出力 (-l
オプション) を行い、かつ更新日時順に並べ替え ( -t
) 、並び順を逆順とする ( -r
) 別名を定義することができます:
>
alias lt='ls -ltr'
全ての別名定義を一覧で表示するには、 alias
とだけ入力して実行します。また、別名定義を削除するには、 unalias
に続いて別名を指定します。
シェルでは変数をローカルかグローバルに設定することができます。グローバル変数は環境変数とも呼ばれ、全てのシェルからアクセスすることができます。逆にローカル変数は、現在のシェルからしかアクセスできないものを指します。
全ての環境変数を出力するには、 printenv
を使用します。変数の値を知りたい場合は、コマンドの後ろに変数名を指定します:
>
printenv PATH
グローバル変数でもローカル変数でも、 echo
コマンドを使用すれば値を出力することができます:
>
echo $PATH
ローカル変数を設定するには、変数名に続いてイコール記号を付け、その後ろに値を記述します:
>
PROJECT="SLED"
なお、イコール記号の後には空白 (スペース) を入れないでください。空白を入れてしまうと、エラーになってしまいます。環境変数を設定したい場合は、 export
というコマンドを使用します:
>
export NAME="tux"
変数を削除するには、 unset
コマンドを使用します:
>
unset NAME
下記の表には、シェルスクリプト内で使用することのできる一般的な環境変数を示しています:
|
現在のユーザのホームディレクトリ |
|
現在のホスト名 |
|
ツールがローカライズ (各国語に翻訳) されている場合、この環境変数を利用して言語を判断します。英語環境の場合は、 |
|
シェルがプログラムを検索する際のパスの一覧です。コロン区切りでディレクトリを並べます |
|
各コマンドの前に表示される、一般ユーザ向けのプロンプト |
|
複数行のコマンドを実行する際に表示される、 2 行目以降のプロンプト |
|
現在の作業ディレクトリ |
|
現在のユーザのユーザ名 |
たとえば 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" "" ""
変数置換は、変数の値に対して左側もしくは右側からパターンを適用する処理を行います。下記のような書式が用意されています:
${変数#パターン}
左側からパターンに該当する最短の部分を削除します:
>
file=/home/tux/book/book.tar.bz2>
echo ${file#*/} home/tux/book/book.tar.bz2
${変数##パターン}
左側からパターンに該当する最長の部分を削除します:
>
file=/home/tux/book/book.tar.bz2>
echo ${file##*/} book.tar.bz2
${変数%パターン}
右側からパターンに該当する最短の部分を削除します:
>
file=/home/tux/book/book.tar.bz2>
echo ${file%.*} /home/tux/book/book.tar
${変数%%パターン}
右側からパターンに該当する最長の部分を削除します:
>
file=/home/tux/book/book.tar.bz2>
echo ${file%%.*} /home/tux/book/book
${変数/パターン_1/パターン_2}
変数 の値のうち、PATTERN_1 を PATTERN_2 で置き換えます:
>
file=/home/tux/book/book.tar.bz2>
echo ${file/tux/wilber} /home/wilber/book/book.tar.bz2
シェルでは、条件分岐などのためにコマンドをグループ化したり組み合わせたりすることができます。それぞれのコマンドには終了コードが決められていて、操作が成功したのか失敗したのかが分かるようになっています。 0 (ゼロ) はコマンドが成功したことを、それ以外の場合は何らかの失敗があったことを示します (値の意味は、コマンドによって異なります) 。
下記の表では、様々なグループ化の方法を示しています:
コマンド_1 ; コマンド_2
コマンドを順次実行します。終了コードについては何もチェックを行いません。下記の例では、 cat
コマンドでファイルの内容を出力したあと、終了コードをチェックせずに ls
コマンドを実行し、ファイルの情報を出力します:
>
cat filelist.txt ; ls -l filelist.txt
コマンド_1 && コマンド_2
左側のコマンドが成功した場合にのみ、右側のコマンドを実行します (論理積) 。下記の例では、ファイルの内容を出力したあと、その出力が成功した場合にのみ、ファイルの情報を出力します:
>
cat filelist.txt && ls -l filelist.txt
コマンド_1 || コマンド_2
左側のコマンドが失敗した場合にのみ、右側のコマンドを実行します (論理和) 。下記の例では、 /home/tux/foo
ディレクトリの作成が失敗した場合にのみ、 /home/wilber/bar
ディレクトリを作成します:
>
mkdir /home/tux/foo || mkdir /home/wilber/bar
関数名(){ ... }
シェル関数を作成します。関数のパラメータは位置パラメータを使用して所得することができます。たとえば下記の例では、短いメッセージを出力する hello
という関数を定義します:
>
hello() { echo "Hello $1"; }
関数の呼び出しは、下記のようにして行います:
>
hello Tux
上記を実行すると、下記のように出力されます:
Hello Tux
スクリプトの流れを制御するため、シェルには while
, if
, for
, case
の各要素が提供されています。
if
コマンドは条件分岐を行うことができるコマンドです。たとえば下記の例では、現在のユーザが Tux であるかどうかによって、出力されるメッセージが変わる仕組みを作っています:
if test $USER = "tux"; then echo "Hello Tux." else echo "You are not Tux." fi
test 表現を使用することで、より複雑かつできるかぎりシンプルな構造を作成することができます。下記の例では、 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 をお読みください。
for
コマンドによるループの作成 #Edit sourcefor
は一連のコマンドを繰り返し実行するための表現です。下記の例では、カレントディレクトリ内にある PNG ファイルの情報を出力しています:
for i in *.png; do ls -l $i done
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 (英語)