少数のコマンドをrootとして実行する必要があり、コマンドの大部分はSudoの前に通常のユーザーとして実行する必要がある、長時間にわたる実行中のbashスクリプトがあります。ファイル所有権などを台無しにするためです。
いくつかの方法を思いつきましたが、それぞれに問題があります
方法1:ファイル内でのSudoの使用
#!/bin/bash
Sudo echo "I must be run by root"
touch needsToBeOwnedByUser1
echo "needs to be run by user"
sleep 1000
Sudo echo "I, again, must be run by root"
コードの記述方法からすると、これは見栄えがよくなります。 Sudo
は、rootで実際に実行する必要があるいくつかのステートメントの前に記述されますが、各Sudo
呼び出し間の時間が長すぎる場合は、Sudo
が再度パスワードを要求します。また、Sudo
の最初の実行が失敗した場合、たとえばパスワードが無効なため、スクリプトの残りの部分は引き続き実行されます。
方法2:Sudoを使用してファイルを呼び出し、必要に応じて元のユーザーに戻す
#!/bin/bash
echo "I must be run by root"
su username -c 'touch needsToBeOwnedByUser1'
su username -c 'echo "needs to be run by user"'
su username -c 'sleep 1000'
echo "I, again, must be run by root"
ほぼすべての行の前にsu username -c
を追加する必要があるため、これも面倒です。 Sudo
の後に元のユーザー名を見つけることも可能ですが、面倒です。
もっと良い方法はありますか?
編集:私が話していることを示すために、ここでは小さな無意味なスクリプトのみを投稿しました。実際のスクリプトには、Sudoを必要とする行(サービスの開始と停止)、Sudoが存在するかどうかに関係ない行、およびSudoなしで実行する必要のある行が多数あります。
方法2に関しては、関数を使用する方が簡単です。例えば:
#!/bin/bash
func(){
echo "Username: $USER"
echo " EUID: $EUID"
}
export -f func
func
su "$Sudo_USER" -c 'func'
$Sudo_USER
は、sudoerのユーザー名です。代わりに$(logname)
を使用することもできます。
私のマシンで実行する:
$ Sudo bash test.sh
[Sudo] password for wja:
Username: root
EUID: 0
Username: wja
EUID: 1000
man sudoers
を読むと、次のことがわかります。
PASSWD and NOPASSWD
By default, Sudo requires that a user authenticate him or herself
before running a command. This behavior can be modified via the
NOPASSWD tag. Like a Runas_Spec, the NOPASSWD tag sets a default for
the commands that follow it in the Cmnd_Spec_List. Conversely, the
PASSWD tag can be used to reverse things. For example:
ray rushmore = NOPASSWD: /bin/kill, /bin/ls, /usr/bin/lprm
would allow the user ray to run /bin/kill, /bin/ls, and /usr/bin/lprm
as root on the machine rushmore without authenticating himself.
したがって、ホストでregular
を許可し、machine1
でcommand1
およびcommand2
をルートとして実行できます。withoutパスワード認証:
reguser machine1 root = NOPASSWD: /usr/local/command1, /usr/local/command2
ただし、詳細についてはman -k Sudo
をそれぞれお読みください。