ディレクトリを変更してからコマンドをリンク( `exec`)しますか? [コピー]

ディレクトリを変更してからコマンドをリンク( `exec`)しますか? [コピー]

特定のディレクトリで任意のコマンドを実行できるコマンドはありますか?

Debian 10 では簡単に使用できますenv --chdir。ただし、env --chdirDebian 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» )

括弧は組み込み()サブシェルを生成し、コマンドなどを生成します。したがって、プロセスの数は同じです。また、環境変数を操作するため、必要ありません。cdsudoenvsudoenvsudo

答え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" ...

関連情報