更改目录然后链接(`exec`)命令?

更改目录然后链接(`exec`)命令?

是否有一个命令可以在特定目录中运行任意命令?

在 Debian 10 中,我可以简单地使用env --chdir。但是,env --chdir在我安装的 Debian 9 上不可用。

我想要运行的命令的一部分由 shell 变量组成,这些变量可能包含空格或其他特殊字符。例如,假设我想要运行的命令是:

strace -- "$@"

因此,以下内容将不起作用:

sudo -i sh -c 'cd my-directory && exec strace -- "$@"'

呃,你为什么要这么做?

我想使用sudo -i/sudo --login来运行命令。但我想在特定目录中运行该命令,而不是root用户的主目录。虽然sudo可以设置环境变量,但似乎没有更改目录的选项。

我使用它sudo -i是因为:1)我希望我正在运行的程序(我的 Ansible playbook)具有HOME=/root,这将避免程序在我的主目录中创建 root 拥有的文件。 2) 这听起来像是一系列 with sudowithout问题的例子-i;一个全新的环境听起来是解决我的问题的最原则的方法。

答案1

我将忽略exec-i因为尚不清楚您对这些问题的要求是什么。

然而到cdsudo,然后

( cd «a directory»; sudo «a command» )

括号()创建一个子shell,cd是内置的,然后是命令sudo什么的。所以进程数与 相同envsudo还操纵环境变量,因此可能不需要envsudo

答案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

运行由目标用户的密码数据库条目指定的 shell 作为登录 shell。这意味着 shell 将读取特定于登录名的资源文件,例如 .profile、.bash_profile 或 .login。如果指定了命令,则会通过 shell 的-c选项将其传递到 shell 执行。

sh -c采用单个字符串参数。因此,它的工作效果如何,取决于与sudo用户 shell 的引用约定的匹配程度。 Shell 引用非常可怕。

在实践中,当我尝试这个时,我发现某物奇怪的事情可能会发生。其他人的分析表明引用sudo可能是“令人惊讶的”或“可怕的”。看:如果我从“sudo --login”运行“sh -c”,则它不会扩展位置参数。有没有解决的办法?

这是实现我真正目标的另一种方法。它不需要创建单独的脚本文件,但我们可以将它很好地包装为 shell 函数:

run_as_root() {
    sudo --set-home \
         bash -l \
              -c 'exec "$@"' \
              bash \
              "$@" 
}

解释:

  • sudo --set-home- 以另一个用户身份运行命令。一些环境发生了改变,但另一些环境则被保留。强制HOME设置为新用户主目录。
  • bash -l- 运行“登录 shell”,初始化环境。这假设您的root用户尚未定制为使用与 不同的 shell bash
  • bash -c 'inline shell script' arg0 arg1 arg2...- 运行一个小的 shell 脚本。 $0被设置为arg0$1被设置为arg1等。注意$0是特殊的。 shell 将$0其视为自己的名称。当 shell 打印错误消息时,错误消息以 开头$0:。因此,我们应该设置arg0bash
  • exec- 用另一个程序替换 shell 进程。
  • "$@"- 扩展到"$1" "$2" ...

相关内容