UNIX/Linuxの部屋 コマンド:exec

TOP UNIX/Linuxの部屋 UNIX/Linuxコマンド一覧 用語集 新版 由来/読み方辞書 環境変数マニュアル Cシェル変数 システム設定ファイル システムコール・ライブラリ ネットワークプログラミングの基礎知識 クラウドサービス徹底比較・徹底解説




コマンド exec 現在実行中のシェルに代わり、指定したコマンドを実行する このエントリーをはてなブックマークに追加

最終更新


UNIX/Linux の exec コマンドは、現在実行中のシェルに代わり、指定したコマンドを実行する sh・bash・csh・tcsh などの内部コマンド (組み込みコマンド・ビルトインコマンド) である。コマンドラインから人間が直接 exec コマンドを叩くことはほとんどなく、シェルスクリプトから異なるコマンドを実行する際に、プロセス数を抑えてシステムリソースを節約する目的で使用されることがほとんどである。

目次:


exec コマンドの概要
まずは基礎知識から。sh・bash・csh・tcsh などのシェルから
% ls
などとコマンドを実行すると、シェルは以下のことを行う。
  • システムコール fork(2) を呼び、子プロセスを生成する。
  • 子プロセスは ls を exec(2) する。
  • 親プロセスであるシェルは、ls の実行が完了するのを待つ (wait する)。

一方、
% exec ls
と exec を使うと、シェルは fork(2) せず、いきなり ls コマンドを exec(2) する (シェルの内部コマンド exec(1) を実行すると、内部でシステムコール exec(2) が呼ばれるということ)。シェルのプロセス情報は ls のプロセスの情報で上書きされる。なお、子プロセスは生成されないので、シェルと ls のプロセス ID は同じになる。

実際にやってみるとわかるが、ssh でログインした状態で、
% exec ls
とすると一瞬 ls の結果が実行されるが、シェルは終了してしまう。これは sshd はシェルの終了を待っているが、シェルのプロセスは ls のプロセスに上書きされ、なおかつ ls のプロセスはすぐに終了してしまうので、ls の終了後、即座に sshd も終了してしまうわけである。

同様に、X Window System 上で kterm などのターミナルを実行中に
% exec ls
とすると、kterm は閉じてしまう。これも、kterm はシェルの終了をを待っているが、シェルのプロセスは ls のプロセスに上書きされるので、ls が終了すると kterm も終了してしまうということだ。

exec コマンドのつかいどころは以下のとおり。

例 1. ~/.xinitrc や ~/.xsession
~/.xinitrc や ~/.xsession では、通常 kterm などの端末エミュレータを数個呼び、twm や fvwm などのウィンドウマネージャを起動する。ここで
#!/bin/sh
kterm -g 102x60+10+10 &
kterm -g 90x52-10-10 &
twm
ではなく、
#!/bin/sh
kterm -g 102x60+10+10 &
kterm -g 90x52-10-10 &
exec twm # ここで exec を使う
と書くとよい。前者は twm を実行している間 (≒ユーザがログインしている間)、sh がずっと twm の終了を待っている。しかし後者は sh のプロセスは twm のプロセスで上書きされてしまうので、前者よりプロセス数が一つ少なくてすむ。

例 2. wrapper スクリプト
例えば FreeBSD 4.7-RELEASE の /usr/bin/pagesize。中身は以下のような sh スクリプトで、sysctl を実行するだけの wrapper (ラッパー) スクリプトである。
#!/bin/sh -
PATH=/bin:/usr/bin:/sbin:/usr/sbin; export PATH
exec sysctl -n hw.pagesize
これも sysctl を実行する間、/bin/sh を待たせなくてよいという効果がある。

同様に、FreeBSD 4.7-RELEASE で調べてみると、
  • /usr/bin/clear は tput を exec する
  • /usr/bin/sockstat は netstat を exec する
  • /usr/bin/perldoc は perl を exec する
  • gs 付属のプログラム (pf2afm、ps2pdf など) は gs を exec する
などなど、多くの wrapper スクリプトが exec でコマンドを呼んでいる。

exec コマンドのまとめ
exec コマンドによる効果は以下の通り。
  • fork(2) で子プロセスを生成しなくてすむ。fork(2) はかなり重いシステムコールである。fork(2) が重いので、vfork(2) が作られたくらい重い。ただ、現代の UNIX では copy-on-write の効果により、以前ほど fork(2) が重いわけではない。
  • 親プロセスが子プロセスの終了を待つ必要がない。1 プロセス分浮くわけである。

exec コマンドを 1回使うことによる速度向上・メモリ量削減効果はたいしたことはない。ただし数百回・数千回分続くようなら、塵も積もれば…となる。例えば大学のような「1つの大型サーバと数十台の X 端末」という状況で、上記の例 1 を考えると、
twm
の部分を
exec twm
とするだけで、一気に数十プロセスが浮くわけである。

関数 exec コマンドを実行 このエントリーをはてなブックマークに追加

exec 系のライブラリ関数には
execl
execle
execlp
exect
execv
execvp
execvP
がある。これらは最終的にシステムコール execve(2) を呼び出す。