web-dev-qa-db-ja.com

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

サンプルスクリプトは次のようになります。

#!/bin/bash
Sudo su
ls /root

./test.shを通常のユーザーとして使用する場合、代わりにlsをスーパーユーザーとして実行して終了すると、rootに切り替わります。ログアウトすると、通常のユーザーとしてls /rootが実行されます。

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

37
Hongxu Chen

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

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

あなたがしたいことは、ラッパースクリプトを書くことです。特権コマンドは、メインスクリプトに含まれます(例:~/main.sh

#!/bin/sh
ls /root

ラッパースクリプトは、次のようにroot権限でメインスクリプトを呼び出します

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

このプロセスを起動するには、ラッパーを実行します。ラッパーは、ユーザーをrootユーザーに切り替えた後にメインスクリプトを起動します。

このラッパー手法を使用して、スクリプトをそれ自体のラッパーに変えることができます。基本的に、ルートとして実行されているかどうかを確認し、実行されていない場合は、「su」を使用して自身を再起動します。

$ 0はスクリプトにそれ自体を参照させる便利な方法であり、whoamiコマンドは私たちが誰であるか(私たちはrootですか?)

したがって、組み込みラッパーを持つメインスクリプトは次のようになります。

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

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

50
Johan

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

Sudo su <<HERE
ls /root
HERE

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

20
Ankit

追加の引数がない場合、suはrootのログインシェルを実行します。これが、スクリプトの最初の行が実際に行うことです。終了すると、ログインシェルが閉じてsuが返され、スクリプトが実行を継続します。つまり、2行目です:ls /root。単純にSudo ls /rootやりたいことを行う。

6
Bananguin

スーパーユーザーの有効なuserid (euid=EUID)を使用してSudo su新しいプロセスをフォークすると、同じ端末に関連付けられた別のプロセスID (pid=PID)で新しいbashが実行されます(tname=TTY)

説明

ps -A | grep bashを実行した後、出力として21460 pts/2 00:00:00 bashがあるとします。これで、./test.shを実行すると、Sudo suls /rootの両方のコマンドがPID 21460にスプールされます。実行後、rootがアクティブユーザーとしてps -A | grep bashを押したときに、PID say, 21570で新しいbashが実行されていることがわかります。 root bashを終了すると、新しく分岐したbashが終了してuser's bashに戻り、プロンプトを解放する前にスプールされたコマンドls /rootを実行します。

1
sundeep