そのユーザーとしてsuを使用して残りのbashスクリプトを実行するにはどうすればよいですか?


126

ユーザー名とプロジェクトを連結した文字列を引数として取るスクリプトを作成しました。スクリプトは、ユーザー名に切り替え(su)、プロジェクト文字列に基づいて特定のディレクトリに移動することになっています。

私は基本的にやりたいです:

su $USERNAME;  
cd /home/$USERNAME/$PROJECT;  
svn update;  

問題は、一度suを実行すると...そのまま待機することです。実行フローがユーザーへの切り替えに渡されているため、これは理にかなっています。終了すると、残りの処理は実行されますが、期待どおりに動作しません。

suをsvnコマンドの前に付加しましたが、コマンドは失敗しました(つまり、目的のディレクトリのsvnを更新しませんでした)。

ユーザーがユーザーを切り替えて(特に)svnを起動できるスクリプトを作成するにはどうすればよいですか?

回答:


86

コツは「su」の代わりに「sudo」コマンドを使用することです

これを追加する必要があるかもしれません

username1 ALL=(username2) NOPASSWD: /path/to/svn

/ etc / sudoersファイルに

スクリプトを次のように変更します。

sudo -u username2 -H sh -c "cd /home/$USERNAME/$PROJECT; svn update" 

ここで、username2はSVNコマンドを実行するユーザーであり、username1はスクリプトを実行するユーザーです。

このスクリプトを実行するために複数のユーザーが必要な場合%groupnameは、username1の代わりに


同様の問題がありますchshが、他のユーザーのために実行したいと思いました。私の問題は、stackoverflow.com / q / 15307289/80353にリストされています。自分の状況にどのように回答を適応させますか?
キムスタック

私はこれを行いました-それでもパスワードを要求しました。
Hippyjim 2013年

@Hippyjimあなたはあなたが正しい方法でユーザー名を手に入れましたか?
Kimvais 2013年

1
私はそうしました-私も/ bin / bashの使用を許可する必要があることがわかりました。
Hippyjim 2013年

3
どちらを使用するsudosu、2番目に重要かsudoは、はるかに安全で便利です。
tripleee 2015

105

はるかに単純:sudoシェルを実行するために使用し、コマンドを供給するためにヒアドキュメントを使用します。

#!/usr/bin/env bash
whoami
sudo -i -u someuser bash << EOF
echo "In"
whoami
EOF
echo "Out"
whoami

元々はSuperUserで回答)


5
この答えが最も効果的でした。オプションを使用-iして、someuserの期待される環境を取得することをお勧めします。
not2savvy 2017年

2
sudo便利かもしれませんが、(AIXのように)箱から出していないのは良くありません。su -c 'commands'正解です。
Tricky

1
エピックソリューション!
3bdalla

herdocのスコープで変数を使用できるようにする方法は?
dotslashlu 2018年

AIXでは、このエラーをスローしますksh:sh:0403-006実行許可が拒否されました。
AhmedRana

54

次のようなスクリプトを使用して、残りのスクリプトまたはスクリプトの一部を別のユーザーで実行します。

#!/bin/sh

id

exec sudo -u transmission /bin/sh - << eof

id

eof

11
「sudo -i -u ...」を使用して、$ HOMEなどが正しく設定されていることを確認できます。
ブライアンラーセン2014

noobの質問で申し訳ありませんが、ここにIDはありますか?
Nitin Jadhav

1
@NitinJadhav、彼は現在のユーザーのIDを表示するためだけにここで使用しました。ルートのIDは0なので、最初のIDはいくつかの番号を表示しますが、2番目は明確に0を表示します(2番目が内部で実行されたため)ルートによって実行されるブロック)。ユーザーはwhoami代わりにidIDの代わりに名前を返すことができます
Mohammed Noureldin

@MohammedNoureldinありがとう!
Nitin Jadhav、2016

sudo便利かもしれませんが、(AIXのように)箱から出していないのは良くありません。su -c 'commands'正解です。
トリッキー

52

すべての異なるユーザーコマンドを独自のスクリプトとして実行する必要があります。それが1つまたはいくつかのコマンドである場合、インラインは機能するはずです。コマンドがたくさんある場合は、コマンドを独自のファイルに移動することをお勧めします。

su -c "cd /home/$USERNAME/$PROJECT ; svn update" -m "$USERNAME" 

4
これが唯一の正解です。これにはsudoは必要ありません。
ヘルベテ

1
シェルにを提供する必要がある場合もありsu -s /bin/bashます。
ミクセル2017年

rootユーザーに最適なソリューション
rfinz

デフォルトでsudoがインストールされていない人のための最良の回答(AIXを探しています)
Tricky

46

これは、私の場合にさらに便利な別のアプローチです(ルート権限を削除し、制限されたユーザーからスクリプトの残りを実行したいだけです)。正しいユーザーからスクリプトを再起動させることができます。最初はrootとして実行されているとします。その後、次のようになります。

#!/bin/bash
if [ $UID -eq 0 ]; then
  user=$1
  dir=$2
  shift 2     # if you need some other parameters
  cd "$dir"
  exec su "$user" "$0" -- "$@"
  # nothing will be executed beyond that line,
  # because exec replaces running process with the new one
fi

echo "This will be run from user $UID"
...

6
なぜこれがもっと高く評価されないのかしら。すべてをbashに保ちながら、元の質問を最良に解決します。
SirVer

またはrunuser -u $user -- "$@"、suコマンドで述べたように(1)
cghislai

1
exec su "$user" "$0" -- "$@"
macieksk 2018

1
@macieksk、ありがとうございます。更新されます。--本当に便利です。
MarSoft、2018

1
提示されたアプローチはすべての中で最高であり、完全です。すべてが単一のスクリプト内に記述されており、すべてbashを使用しています。事実上、このスクリプトは2回実行されます。最初はスクリプトテストでrootになり、次に環境を準備し、suでユーザーを変更します。ただし、execコマンドを使用すると、スクリプトインスタンスは1つだけになります。2番目のループでは、if / fiを省略すると、スクリプトは直接準備されたアクションを実行します。この例では、エコーです。他のアプローチはすべて、問題を部分的にしか解決しません。もちろん、このスクリプトはbashではなくshで実行できますが、$ UIDではなく$ HOME特殊変数をテストする必要があります
Znik

7

sudo代わりに使用

編集:ダグラスが指摘したようcdsudo、それは外部コマンドではないので使用できません。機能させるには、サブシェルでコマンドを実行する必要がありますcd

sudo -u $USERNAME -H sh -c "cd ~/$PROJECT; svn update"

sudo -u $USERNAME -H cd ~/$PROJECT
sudo -u $USERNAME svn update

そのユーザーのパスワードの入力を求められる場合がありますが、1回だけです。


ただし、これは機能しません。最初のsudoの実行が終了すると、CDは失われます。
ダグラスリーダー2010年

実際、cdは外部コマンドではないため、直接呼び出すこともできません。
iamamac

sudo便利かもしれませんが、(AIXのように)箱から出していないのは良くありません。su -c 'commands'正解です。
Tricky

6

シェルスクリプト内でユーザーを変更することはできません。他の回答で説明されているsudoを使用した回避策は、おそらくあなたの最善の策です。

rootとしてperlスクリプトを実行するのに十分な気が狂っている場合は、次のように、$< $( $> $) 実際の/有効なuid / gidを保持する変数を使用してこれを実行できます。

#!/usr/bin/perl -w
$user = shift;
if (!$<) {
    $> = getpwnam $user;
    $) = getgrnam $user;
} else {
    die 'must be root to change uid';
}
system('whoami');

-1これは、とIS一時的に他のユーザーの権利を得るためにはsudoで可能。
Kimvais

4
ユーザーがシェルスクリプト自体を変更できないように実行するという意味では不可能です(これは元の質問が尋ねたものです)。sudoを使用して他のプロセスを呼び出しても、スクリプト自体の実行者は変更されません。
Pナット

2

これは私のために働いた

「スタートアップ」から「プロビジョニング」を分割しました。

 # Configure everything else ready to run 
  config.vm.provision :shell, path: "provision.sh"
  config.vm.provision :shell, path: "start_env.sh", run: "always"

それから私のstart_env.shに

#!/usr/bin/env bash

echo "Starting Server Env"
#java -jar /usr/lib/node_modules/selenium-server-standalone-jar/jar/selenium-server-standalone-2.40.0.jar  &
#(cd /vagrant_projects/myproj && sudo -u vagrant -H sh -c "nohup npm install 0<&- &>/dev/null &;bower install 0<&- &>/dev/null &")
cd /vagrant_projects/myproj
nohup grunt connect:server:keepalive 0<&- &>/dev/null &
nohup apimocker -c /vagrant_projects/myproj/mock_api_data/config.json 0<&- &>/dev/null &

-2

@ MarSoftのアイデアに触発されましたが、次のように行を変更しました。

USERNAME='desireduser'
COMMAND=$0
COMMANDARGS="$(printf " %q" "${@}")"
if [ $(whoami) != "$USERNAME" ]; then
  exec sudo -E su $USERNAME -c "/usr/bin/bash -l $COMMAND $COMMANDARGS"
  exit
fi

私は以前sudo、パスワードを使用しないスクリプトの実行を許可してきました。ユーザーのパスワードを入力する場合は、を削除しsudoます。環境変数が必要ない場合は-E、sudoから削除してください。

/usr/bin/bash -lことを保証し、profile.dスクリプトが初期化された環境のために実行されます。


sudo便利かもしれませんが、(AIXのように)箱から出していないのは良くありません。su -c 'commands'正解です。
Tricky

@トリッキーおそらく完全な答えを読んでください、それはすでに削除することを提案していsudoます。実際、sudoはそれほど単純ではありません。多くの場合sudo -E、sudoers.dに構成エントリがあり、ttyなしで実行できるようにする必要があります!requiretty。ただし、自動呼び出しスクリプトにsudoが必要な場合が多く、パスワードダイアログが干渉する場合があります。したがって、私はそれを標準ソリューションから削除しません。
Trendfischer 2018年

問題のコードは完全にバグがあり、スクリプト名や引数がスペースで区切られます。"$@"文字列の内側に置くと、最初の引数を超えた引数は別の文字列に追加され、引数に含まれません-c。安全にしたい場合はprintf -v arg_q '%q ' "$0" "$@"、次の方法を使用できますsu "$USERNAME" -c "/usr/bin/bash -l $arg_q"
Charles Duffy

@CharlesDuffyそうですね!私はこの回答のために生産スクリプトを単純化しすぎました:-(を追加するだけでCOMMANDARGS=$@問題が解決しました-c。スペースを含む引数は以前は問題ではありませんでしたが、私はあなたの良い入力を実装しました。私はそれを機能させるためにいくつかの実験をしなければなりませんでした。私は。。「質問を編集し、うまくいけば、私は、あなたのコメントをありがとう、別のバグを貼り付け屈辱が、必要ではなかったVEの
Trendfischer
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.