~によると須藤(8):
Process model
sudoは、コマンドを実行するときにfork(2)を呼び出し、上記のように実行環境を設定し、サブプロセスでexecveシステムコールを呼び出します。
また、フォークされたサブプロセスがsh
。
したがって、コマンドがいくつかのbash関連コマンド(例えばsource
そのコマンド)を含むbashスクリプトである場合、sh
正しく実行されません。たとえば、
%猫/tmp/wibble 何かソース %ls -l /tmp/wibble -rwxr-xr-x ユーザー 1人 user17 8月24日 08:32 /tmp/wibble %パスワードルートを取得する ルート:x:0:0:ルート:/ルート:/bin/bash % /tmp/スイング /tmp/wibble: 1: /tmp/wibble: ソース: 見つかりません % /bin/bash /tmp/wibble ~ [pts/3.4028.1] /tmp/wibble: 行1: 何か: そのファイルやディレクトリはありません。 % /bin/dash /tmp/wibble /tmp/wibble: 1: /tmp/wibble: ソース: 見つかりません % /bin/sh /tmp/wibble /tmp/wibble: 1: /tmp/wibble: ソース: 見つかりません %エコ$ SHELL /bin/zsh % sudo /tmp/wibble /tmp/wibble: 1: /tmp/wibble: ソース: 見つかりません % sudo -s /tmp/wibble /tmp/wibble: 1: /tmp/wibble: ソース: 見つかりません % sudo -i /tmp/wibble /tmp/wibble: 行1: 何か: そのファイルやディレクトリはありません。 % エクスポート SHELL=/bin/bash % sudo /tmp/wibble /tmp/wibble: 1: /tmp/wibble: ソース: 見つかりません % sudo -s /tmp/wibble /tmp/wibble: 行1: 何か: そのファイルやディレクトリはありません。 % sudo -i /tmp/wibble /tmp/wibble: 行1: 何か: そのファイルやディレクトリはありません。 %
-s
通常、この問題を解決するために前の例のようにオプションを追加できますが、デフォルトが使用されているsudo
理由を知りたいです。これを別のシェルで構成できますか?sudo
sh
答え1
スクリプトが#!
適切な-lineで始まることを確認してください。
スクリプトが実行可能で、たとえば次のように始まる場合
#!/bin/bash
(またはシステムへのすべてのパスbash
)の後にスクリプトが続きます。〜する/bin/bash
sudo script
と入力すると、Pythonスクリプトは最初の行がとして解釈される/usr/bin/python
かのように解釈されます#!/usr/bin/python
。
sh
シェルbash
や他のシェルに関する質問はここでは興味深いものではありません。一般的に言えば、各タイプのシェルには相互に排他的なスクリプト言語があるとします。そして#!
-line を使ってスクリプトするインタプリタを正確に指定します。たとえば、POSIX構文と構文のみを使用して移植可能なスクリプトを作成する場合、#!/bin/sh
POSIXシェルを拡張する配列やその他の項目を#!/bin/bash
使用する場合を使用します。bash
テキストファイル#!
。/bin/sh
これとは関係ありませんsudo
。
更新された質問では、-lineなしでスクリプトへの複数の呼び出しを表示します#!
。インタプリタがsource
コマンド(source: not found
)を理解していないか、ファイル(something: No such file or directory
)を見つけることができないため、すべて失敗します。
要約すると、スクリプトのインタプリタを指定するには、常に -line を使用します#!
。
source
また: を使用するとき./something
。$PATH
関連:
答え2
更新:質問が大幅に修正されたので、私の答えでなければなりません。
「スクリプト」と見なされるものの標準定義がないことがわかりましたが、単にコマンドリストを含むファイルであっても、シェルによって実行される限り、「スクリプト」になります。したがって、スクリプトの上部にシェルが指定されていない場合は、デフォルトの動作(sh)が採用されることに注意してください。
前の回答:bashが現在のシステムにない場合、bashismを理解できないため、スクリプトは失敗するはずです
。実験してみよう!sh
~/Downloads/test$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 8月 31 2016 /bin/sh -> dash
sh
まず、そうでないことを確認してくださいbash
。を使用して別のbashスクリプトを呼び出し
bash.sh
ます。bash
sudo
:~/Downloads/test$ cat bash.sh
#!/bin/bash
sudo ./sudo_bash.sh
dash.sh
((i++))
あなたの言葉に従ってbashismが失敗しなければならないことを示すダッシュスクリプト。
:~/Downloads/test$ cat dash.sh
#!/bin/sh
i=0
((i++))
echo $i
確認しよう
:~/Downloads/test$ ./dash.sh
./dash.sh: 4: ./dash.sh: i++: not found
0
:~/Downloads/test$
美しく失敗しました。これでsudo_bash.sh
bashスクリプトです。 sudoコマンドを使用してbash.shで実行します。おっしゃったように実際に分岐した場合でもsh
失敗しなければなりません。
:~/Downloads/test$ cat sudo_bash.sh
#!/bin/bash
i=0
((i++))
echo $i
:~/Downloads/test$ ./bash.sh
[sudo] password for cs-server:
1
:~/Downloads/test$
実行成功。これは新しい環境が利用できないことを証明します/bin/sh
。
I'd like to know why sudo uses sh as default.
歴史的に、最初のシェルはshだったので、互換性のために名前が保持されます。
Is it so that it can be configured to other shells?
もちろん、shのシンボリックリンクを変更するだけです。
:~/Downloads/test$ cat text_file
i=0
((i++))
echo $i
:~/Downloads/test$ chmod +x text_file
:~/Downloads/test$ sudo ln -sf bash /bin/sh
:~/Downloads/test$ sudo ./text_file
1
:~/Downloads/test$ sudo ln -sf dash /bin/sh
:~/Downloads/test$ sudo ./text_file
./text_file: 2: ./text_file: i++: not found
0