シェルスクリプトで「sudo su」が残りのスクリプトをrootとして実行しないのはなぜですか?

シェルスクリプトで「sudo su」が残りのスクリプトをrootとして実行しないのはなぜですか?

スクリプトの例は次のとおりです。

#!/bin/bash
sudo su
ls /root

./test.sh一般ユーザーとして使用すると、lsスーパーユーザーとして実行されるように変更および終了し、ログアウトするとls /root一般ユーザーとして実行されます。

誰でもそのメカニズムについて教えてもらえますか?

答え1

スクリプトのコマンドは、1 つずつ独立して実行されます。スクリプト内のすべてのコマンドの親プロセスであるスクリプト自体は別の独立したプロセスです。 suコマンドはそれをrootに変更せず、変更することもできません。 suコマンドは、root権限を持つ新しいプロセスを作成します。

suコマンドが完了した後も同じユーザーとして実行されている親プロセスは、スクリプトの残りの部分を実行します。

あなたが望むのはラッパースクリプトを書くことです。特権コマンドはデフォルトスクリプトに移動します。~/main.sh

#!/bin/sh
ls /root

ラッパースクリプトは、以下のようにroot権限でデフォルトスクリプトを呼び出します。

#!/bin/sh
su -c ~/main.sh root

このプロセスを開始するには、ユーザーを root に切り替えて、基本スクリプトを起動するラッパーを実行する必要があります。

このパッケージング技術により、スクリプトを独自のラッパーに置き換えることができます。デフォルトではrootとして実行されていることを確認し、そうでない場合は「su」を使用して再起動します。

$ 0はスクリプト参照自体を作成する便利な方法で、whoamiコマンドは私たちが誰であるかを教えてくれます(私たちはルートですか?)。

したがって、ラッパーが組み込まれた基本スクリプトは次のようになります。

#!/bin/sh
[ `whoami` = root ] || exec su -c $0 root
ls /root

execの使用に注意してください。これは、「このプログラムを次に置き換える」を意味し、実行を効果的に終了し、最上位からrootとして実行されるsuによって開始された新しいプログラムを起動します。代替インスタンスは「ルート」なので、|| の右側を実行しません。

答え2

スクリプトで次を使用します。

sudo su <<HERE
ls /root
HERE

HEREブロック間のコードはrootとして実行されます。

答え3

追加の引数がない場合、suログインシェルはルートに対して実行されます。これは、スクリプトの最初の行が実際に行うことです。終了すると、ログインシェルが閉じてsuが返され、スクリプトは実行され続けます(例:line 2:)ls /root。ただしたいsudo ls /rootとおりにすればいいと思います。

答え4

root権限で実行するためのスクリプトが必要な場合は、スクリプトの先頭に次のように入力します。

if [ ! $(whoami)=”root” ]; then
    exec sudo ”$0” ”$@”
    echo ”Error: failed to execute sudo” >&2
    exit 1
fi

これにより、同じパラメータを使用してスクリプトが再実行されますが、コマンドが正常に起動するsudoと、sudo最初のスクリプトプロセスが置き換えられ、edバージョンのみが前方に移動します。次の行が実行されると、シェルは起動できなくなり、何かが本当に間違っていることを意味します。execsudoexec sudosudo

ユーザーにスクリプトを実行する権限がある場合は、sudoパスワードを要求したり、要求しないことがあります。無効なパスワードを入力したり、ユーザーがrootとしてスクリプトを実行する権限を持っていない場合は、sudo標準エラーメッセージが表示されます。

成功すると、sudoスクリプトが再起動され、ルート権限で実行されます。if式はそのステップをスキップし、残りのexec sudo...スクリプトを続行します。

したがって、フローは次のようになります。

  • 親:ユーザーがスクリプトを実行するコマンドラインセッション
  • sudochild:元のスクリプトをユーザーとして実行しましたが、後で変更されたシェルです。exec
  • Sun Tzu: ルートとしてスクリプトを実行するシェルです。

関連情報