LoginSignup
0
0

More than 3 years have passed since last update.

外部プログラムを直接実行した場合にシェルスクリプトにフォールバックする言語・しない言語

Last updated at Posted at 2020-09-15

※本記事の内容はWindowsには一切当てはまりません。

※Linux (Debian stretch) / macOS (10.14) で確認。

https://linuxjm.osdn.jp/html/LDP_man-pages/man3/exec.3.html 等によると、execvpでのみ、ENOEXECが発生したらシェルスクリプトと解釈する機能があるそうです。
スクリプト言語でシェルを使わず外部プログラムを実行した場合、この機能は働くのでしょうか?

準備

$ cat lsscript
ls

実行

Ruby

  • 直接実行(例): popenの引数が配列、systemの引数が2要素以上
  • ruby -e 'p IO.popen(["./lsscript"]).read'

process.c proc_exec_cmd
execveを試し、ENOEXECなら/bin/shを付加して再試行

Python

  • 直接実行(例): check_call(等)の引数が配列
  • python -c 'import subprocess;subprocess.check_call(["./lsscript"])'

Modules/_posixsubprocess.c child_exec
execveを試す。 ENOEXECの場合失敗する

Python3も同様。
なおshell=Trueとすると失敗しなくなりますがpipes.quoteやらshlex.quoteやらが必要となります。
(この記事の読者であればこちらの必要性はわかりますよね)

Perl

  • 直接実行(例): system()の引数が2要素以上
  • perl -e 'print system("./lsscript","dummy")'

doio.c Perl_do_aexec5
execvpを試す。

PHP

  • 直接実行: pcntl_exec
  • php -r 'pcntl_exec("./lsscript");'

ext/pcntl/pcntl.c pcntl_exec
execveを試す。 ENOEXECの場合失敗する

(上はexecですからサブプロセスとするにはfork呼び出し等が必要。その辺が必要ない標準実行系はext/standard/exec.cにありますが、popen固定のようです(つまり必ずシェルが入る))

結論

Python/PHPでシェルを介さずに実行しようとすると、自動でshを付けてくれません。C言語のshebangもどき等を投げる際はご注意ください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0