連載
» 2018年05月18日 05時00分 公開

Linux基本コマンドTips(208):【 set 】コマンド(応用編2)――定義されていない変数の扱いやコマンドのエラーへの対応を変更する

本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は、シェルの設定を確認、変更する「set」コマンドです。

[西村めぐみ,@IT]
「Linux基本コマンドTips」のインデックス

Linux基本コマンドTips一覧

 本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回はシェルの設定を確認、変更する「set」コマンドです。

setコマンドとは?

 「set」はシェルの設定を確認、変更するコマンドです。setはbashのビルトインコマンド(シェルの組み込みコマンド)です(※1)。このためmanコマンドではなく、helpコマンドで詳細を表示できます。setコマンドの基本的な使い方については、連載第205回をご確認ください。

※1 tcshなど、他のシェルにも同名のコマンドがある。



 今回はsetコマンドのオプションのうち、よく使われる2つを取り上げます。定義されていない変数を参照したらエラーとする「nounset」オプションと、コマンドが実行時にエラーになった場合、直ちにシェルを終了する「errexit」オプションです。

 リダイレクトで既存のファイルを上書きしない「noclobber」オプションと、[CTRL]+[D]でログアウトしない「ignoreeof」オプション、終了したバックグラウンドジョブの結果をすぐに表示する「notify」オプションについては、第207回をご覧ください。



setコマンドの書式

set [オプション]

※[ ]は省略可能な引数を示しています。




setの主なオプション

短いオプション 意味
-o シェルオプション シェルオプションを有効にする
-o 設定したシェルオプションを「on」と表示する
+o シェルオプション シェルオプションを無効にする(-oによる設定を打ち消す)
+o 設定したシェルオプションを現在と同様に設定するための全てのコマンド列を一覧表示する
--、- オプションの終わり(「--」および「-」以降は全てファイル名やsetコマンドのオプション以外の引数として扱う)

主なシェルオプションとオプション

シェルオプション オプション 意味
allexport -a シェル変数の定義と同時にexportし、環境変数としても使用可能にする(※2)
braceexpand -B ブレース展開を実行する(デフォルトで有効)
noglob -f 「*」などによるパス名展開を無効にする
nounset -u パラメーター展開中に、設定していない変数があったらエラーとする(特殊パラメーターである「@」と「*」は除く)
noclobber -C リダイレクトで既存のファイルを上書きしない
ignoreeof [CTRL]+[D]で終了しない(「IGNOREEOF=10」相当)
physical -P cdコマンドなどでシンボリックリンクをたどらずに物理的なディレクトリ名を使用する
emacs コマンド行の編集操作をEmacs形式にする(デフォルトで有効)
vi コマンド行の編集操作をviコマンド形式にする
posix bashの動作のうち、デフォルトの動作がPOSIXと異なるものもPOSIX準拠になるように変更する(POSIXモード)

※2 「set -a」は「set -o allexport」と同じ効果を持つ。「set +a」は「set +o allexport」相当だ。他のシェルオプションについても同様。



主なシェルオプションとオプション(ヒストリとジョブ関連)

シェルオプション オプション 意味
history コマンド履歴を有効にする(対話シェルではデフォルトで有効)
histexpand -H 「!番号」によるヒストリの参照を行う(デフォルトで有効)
monitor -m 監視モード。バックグラウンドジョブの結果を表示する(デフォルトで有効)
notify -b 終了したバックグラウンドジョブの結果をすぐに表示する(通常は次のコマンド実行時に表示する)
hashall -h コマンドのパスを全て記憶する(hashコマンド参照)

主なシェルオプションとオプション(エラー処理とデバッグ関連)

シェルオプション オプション 意味
errexit -e パイプやサブシェルで実行したコマンドが1つでもエラーになったら直ちにシェルを終了する
pipefail パイプラインの返り値を、最後のエラー終了値(0以外で終了した際の値、全ての実行が成功した場合は0)にする
errtrace -E エラーをトレースする(シェル関数で、ERRトラップを継承する)
functrace -T デバッグをトレースする(シェル関数で、DEBUGトラップを継承する)
verbose -v シェルの入力行を表示する
xtrace -x トレース情報として、シェルが実行したコマンドとその引数を出力する。情報の先頭にはシェル変数PS4の値を使用

主なシェルオプションとオプション(その他)

シェルオプション オプション 意味
interactive-comments 「#」以降をコメントとして扱う(デフォルトで有効)
keyword -k コマンド名の前にある代入文だけでなく、引数として指定した全ての代入文も、そのコマンドに対する環境変数に追加する
noexec -n コマンドを読み込むだけで実行しない(※3)
onecmd -t コマンドを1つ読み込み、実行してから終了する
privileged -p 特権モード。シェル関数や変数を環境から継承せず、実効ユーザーも再設定しない

※3 シェルスクリプトの文法チェックをする際に使用する。対話シェルでは無視する。





定義されていない変数を参照したらエラーとする

 コマンドラインやシェルスクリプトから変数を参照したとき、その変数が定義されていない場合は「値なし」になります。例えば、「echo $testvar」を実行したときに、変数$testvarが定義されていなければ、何も表示しません(画面1)。

 ここでsetコマンドのオプションを使うと、定義されていない変数を参照した際、エラーとなるように設定できます。「set -o nounset」または「set -u」で、setコマンドの「nounset」オプションを有効にします。

コマンド実行例

set -o nounset

(nounsetオプションを有効にする)

set -u

(nounsetオプションを有効にする、set -o nounset相当)(画面1


画面1 画面1 定義されていない変数を参照したときのシェルの挙動を変えたところ

 画面1でも分かるように、nounsetオプションが無効の場合、定義されていない変数を参照してもエラーにはなりません(エラーコードが0になる)。従って、変数の値がないのか、変数そのものが定義されていないのか、区別がつきません(画面2)。

画面2 画面2 変数の値がないのか、変数そのものが定義されていないのか区別ができない

 シェルスクリプト内から、ある変数が定義されているかどうか調べる方法は大きく3つあります。まず「if [ -v 変数名 ]; then 〜」のように調べる方法です(※5)。第2にスクリプトの先頭の方で「set -o nounset」または「set -u」を実行する方法、第3に「#! /bin/bash -u」のようにbashを-uオプション付きで指定する方法です。

※4 「[-v 変数名]」は、条件式を判定するビルトインコマンドであるtestコマンドの-vオプション(「test -v 変数名」)と同じ意味。ここでは変数名が定義されているかどうかを調べている。





コマンドがエラーとなったら直ちにシェルを終了する

 コマンドラインで実行したコマンドがエラーとなっても、通常、シェルは終了しません。そのまま次のコマンドを待ちます。コマンドラインではこのような動作でも問題ありませんが、シェルスクリプトの場合はエラーが起きた時点で終了させたい場合があります。

 エラーが起きた時点で終了させるには、「set -o errexit」または「set -e」でsetコマンドのerrexitオプションを有効にします。

 ただし、set -eを使う対応は、スクリプトを改善し、テストする段階などに留めておくべきです。何度も使うシェルスクリプトでは、エラー処理を書いておきましょう。

コマンド実行例

set -o errexit

(errexitオプションを有効にする)

set -e

(errexitオプションを有効にする、set -o errexit相当)(画面4


 画面3では、シェルの動作を試すために、suコマンド(第67回)でいったん別のユーザー(penguin)に変わり、lsコマンドで存在しないファイルを表示しています。当然lsコマンドはエラーになりますが、シェルは実行を続けています。

 これに対し、errexitオプションを有効にした状態で同じようにlsコマンドを実行すると、エラーとなった時点でシェルが終了し、元のユーザーに戻っている様子が分かります(画面4)。

 ご自身の環境で試す場合、新しい端末画面を開いてそこで実行すれば、suコマンドを使わなくても構いません。「set -e」を実行した後、lsコマンドを同様に実行してエラーになると、端末画面が閉じます。bashが終了する様子が分かるでしょう。

画面3 画面3 存在しないファイルを表示しようとしてもシェルの動作が続いている様子 画面4と動作を比較しよう。
画面4 画面4 set -eの効果を試しているところ エラーが発生するとシェルが終了する


筆者紹介

西村 めぐみ(にしむら めぐみ)

PC-9801NからのDOSユーザー。PC-486DX時代にDOS版UNIX-like toolsを経てLinuxへ。1992年より生産管理のパッケージソフトウェアの開発およびサポート業務を担当。著書に『図解でわかるLinux』『らぶらぶLinuxシリーズ』『Accessではじめるデータベース超入門[改訂2版]』『macOSコマンド入門』など。2011年より、地方自治体の在宅就業支援事業にてPC基礎およびMicrosoft Office関連の教材作成およびeラーニング指導を担当。


Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。