Help us understand the problem. What is going on with this article?

[バグか仕様か?] FreeBSD /bin/shにおける-mオプションの挙動

More than 3 years have passed since last update.

FreeBSDの/bin/shで、他実装とは違うヘンな挙動を見つけたのでメモ書き。

まずは、このテストコード(setm_test.sh)を書いてください。

setm_test.sh
#! /bin/sh

set -m                # ←コレをつけると不可解な動きをする

# 終了時のトラップ設定
exit_trap() {
  trap INT
  echo "EXIT_TRAPPED"
  exit 1;
}
trap 'exit_trap' INT

# メインルーチン(sleepを実行して終了を通知する)
sleep 5 || echo $?
echo "FINISH_SLEEPING"
trap INT

冒頭に出てくる-mというオプションは、ジョブ制御を有効にするためのものです。具体的には、

  • ジョブ完了メッセージ(“[1] Done”のようなメッセ^時)が出る。(非対話のシェルスクリプトのデフォルトでは表示されない)
  • fgコマンドのような、ジョブ制御コマンドが使えるようになる。(非対話のシェルスクリプトのデフォルトでは、エラーメッセージが出て使えない)

などの効果があります。

書いたら実行してみください。

(1)起動するだけで何もせず、終了を待つ。

$ sh setm_test.sh
FINISH_SLEEPING
$ 

5秒経過したらFINISH_SLEEPINGと表示されて終了します。

(2)起動したら5秒以内に[CTRL]+[C]を押して止める

CentOS6,Ubuntu14,AIX7.1で試した場合
$ sh setm_test.sh
^CEXIT_TRAPPED
$ 
FreeBSD10で試した場合
$ ./setm_test.sh
^C130
FINISH_SLEEPING
$ 

なんとOSによって挙動が変わります。FreeBSD以外だと、シェルが[CTRL]+[C]によるSIGINTを受け取ると、現在実行中のsleepコマンドを中断させ、trap設定してあったexit_trap関数へ制御を移します。

ところが、FreeBSDだと、sleepコマンドを中断させた後、そのままメインルーチンを続行してしまうのです。これっておかしくないでしょうか?

シェルではなくOSの問題?それとも仕様?

この問題、bashでも起こります。

FreeBSD10で試した場合
$ bash setm_test.sh
^C130
FINISH_SLEEPING
$ 

shだけで起こるならshのバグと思えそうですが、シェルを替えても起こるのでOSのバグなのか、それともFreeBSDの仕様なのか。

どちらなのか、現状では判断がつきません。(Macとかどうかなのかな?)

心当たりの方、是非コメントください。

richmikan@github
困った時はすぐQiitaを始めとしたTipsを表面的に鵜呑みにし、使えそうなプロダクトを拾ってきてマニュアル通りに対応するプロダクト至上主義者達よ。そんなことでは、想定外の事態に見舞われた時すぐ死ぬぞ。想定外とは、マニュアルには載ってないから想定外なのだ。マニュアル通りにしか動けぬ者は、典型的なコンビニ店員の如く薄給に喘ぐだけ。頭を使え!UNIX哲学に目覚めよ!そしてPOSIX原理主義を崇拝せよ!
https://github.com/ShellShoccar-jpn
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away