特定のディレクトリで任意のコマンドを実行できるコマンドはありますか?
Debian 10 では簡単に使用できますenv --chdir
。ただし、env --chdir
Debian 9インストールでは使用できません。
私が実行したいコマンドの一部は、スペースやその他の特殊文字を含めることができるシェル変数で構成されています。たとえば、私が実行したいコマンドが次のようになっているとします。
strace -- "$@"
したがって、以下は機能しません。
sudo -i sh -c 'cd my-directory && exec strace -- "$@"'
ええ、なぜこれを行うのですか?
sudo -i
/を使ってsudo --login
コマンドを実行したいです。しかし、rootユーザーのホームディレクトリではなく、特定のディレクトリでコマンドを実行したいと思います。環境変数を設定できますが、sudo
ディレクトリを変更するオプションはないようです。
私は次の理由でこれを使用しますsudo -i
:1)私は実行中のプログラム(私のAnsible Playbook)に行きたいですHOME=/root
。これにより、プログラムが自分のホームディレクトリにルート所有ファイルを生成するのを防ぐことができます。 2)これはまったく新しい環境が私の問題を解決する最も原則的な方法のように聞こえますsudo
。-i
答え1
これらの質問に対するあなたの要件が何であるかは明確ではないのでexec
無視します。-i
しかしcd
それsudo
まで
( cd «a directory»; sudo «a command» )
括弧は組み込み()
サブシェルを生成し、コマンドなどを生成します。したがって、プロセスの数は同じです。また、環境変数を操作するため、必要ありません。cd
sudo
env
sudo
env
sudo
答え2
次のような別々のスクリプトを簡単に作成できますchdir
。
#!/bin/sh
dir=$1 &&
shift &&
cd -- "$dir" &&
exec "$@"
別のスクリプトがないと、はるかに曖昧になります。
sh -c 'cd -- "$1" && shift && exec "$@"' sh my-directory "$@"
ただし、これは質問で説明されている実際の目標を達成できません。上記のスクリプトを使用して実行できると考えることもできますsudo --login chdir my-directory ...
。これはほとんどの場合効果があるかもしれませんが、私はそれが悪い考えだと思います。報告man sudo
:
-i
、--login
ターゲットユーザーのパスワードデータベースエントリで指定されたシェルをログインシェルとして実行します。これは、シェルが.profile、.bash_profile、または.loginなどのログイン固有のリソースファイルを読み取ることを意味します。コマンドが指定されると、
-c
シェルのオプションで実行できるようにシェルに渡されます。
sh -c
単一の文字列引数を使用します。したがって、これがどのようにうまく機能するかは、sudo
ユーザーシェルの引用規則とどれだけうまく一致するかによって異なります。シェル引用符はひどいです。
実際にこれを試してみると、次のようになります。何奇妙なことが起こる可能性があります。他の人の分析によると、この引用はsudo
「驚き」または「怖さ」かもしれません。望むより:「sudo --login」で「sh -c」を実行すると、位置パラメータは拡張されません。解決策はありますか?
これが私の本当の目標を達成するもう一つの方法です。別のスクリプトファイルを作成する必要はありませんが、それをシェル関数で素敵にラップできます。
run_as_root() {
sudo --set-home \
bash -l \
-c 'exec "$@"' \
bash \
"$@"
}
説明する:
sudo --set-home
- 他のユーザーとしてコマンドを実行します。一部の環境は変更されましたが、一部の環境はそのまま残りました。HOME
新しいユーザーのホームディレクトリになるよう強制されます。bash -l
- 「ログインシェル」を実行して環境を初期化します。これはroot
、ユーザーが他のシェルを使用するようにカスタマイズされていないと仮定しますbash
。bash -c 'inline shell script' arg0 arg1 arg2...
- 小さなシェルスクリプトを実行します。$0
に設定されているarg0
、$1
に設定されているarg1
などの注目は$0
特別です。シェルは$0
それを自分の名前として扱います。シェルがエラーメッセージを印刷すると、エラーメッセージは$0:
。したがって、arg0
に設定する必要がありますbash
。exec
- シェルプロセスを別のプログラムに置き換えます。"$@"
- 拡張"$1" "$2" ...