如何在 Linux 脚本中以另一个用户身份运行命令

很自然地,当您运行命令或脚本时,系统会将其作为您启动的进程来执行。但是您可以以另一个用户身份运行命令和脚本。
流程有所有者
执行程序或脚本时,Linux 会创建一个进程。该过程有一个所有者。所有者是另一个进程或用户帐户的名称(如果有人启动它)。
进程的所有权定义了进程的一些能力和环境。根据流程的启动方式,它会继承其父流程或用户的某些属性。或者,更严格地说,用户用来启动通常是 shell 的程序的过程。
以另一个用户身份运行命令或脚本可能很有用,因为该进程创建的任何文件的所有权都属于相应的用户。
每次我们使用 sudo
时,我们都以另一个用户的身份运行命令。 sudo
使用的默认用户帐户是根用户或“超级”用户。因此,sudo
经常被误认为代表超级用户执行。但这只是行话。它实际上代表替代用户做。
使用 sudo
,您可以以任何其他用户身份运行命令,而不仅仅是以 root 身份。具有讽刺意味的是,您需要 root 权限才能这样做。但是启动另一个用户拥有的程序或脚本与以该其他用户的身份运行该进程是不同的。您仍将以 root 身份运行它。
以下是如何以另一个用户的身份实际运行一个进程,以及如何从脚本中运行命令,就好像它们已被另一个用户执行过一样。
以另一个用户身份运行脚本
我们正在使用配置了多个用户的计算机。一个是 Mary,用户名是 maryq,另一个是 Dave,用户名是 dave。
Mary 在她的主目录中有一个名为“other-user.sh”的脚本。这是脚本的文本。
#!/bin/bash
echo "Script name:" $0
echo "Working directory:" $(pwd)
echo "Script running as user:" $(whoami)
它打印出保存在 $0
环境变量中的脚本名称。然后它使用 pwd
打印工作目录。最后,它使用 whoami
命令打印启动脚本的用户的名称。或者它认为是谁启动了脚本。
将脚本中的文本复制到编辑器中,并将其保存为不同用户帐户的主目录中的“other-user.sh”。
我们需要使脚本可执行。我们将使用 chmod
命令并使用 +x
(执行)选项和 -u
(用户)选项来设置执行标志仅供所有者使用。这意味着只有 Mary 可以运行该脚本。我们将使用 ls
检查文件权限。
chmod u+x other-user.sh
ls

从左到右,权限为:
- 所有者可以读取、写入和执行文件。
- 群组成员可以读写文件。
- 其他人只能读取该文件。
因此,能够运行该脚本的唯一用户是 Mary 和 root。这是 Mary 运行脚本时发生的情况:
./other-user.sh

我们被告知脚本的当前工作目录是 Mary 的主目录,脚本的所有者是用户帐户 maryq。
不出所料,Dave 无法运行该脚本。
/home/maryq/other-user.sh

如果 Dave 拥有 root 用户权限,他可以尝试使用 sudo
以 root 身份运行脚本。
sudo /home/maryq/other-user.sh

这是部分成功。脚本运行,但脚本的所有者是 root,而不是 maryq。
我们需要使用的技巧是 sudo -u
(用户)选项。这使您可以指定要以其身份运行命令的用户。如果你不使用 -u
选项,sudo
默认使用 root。如果我们想以 Mary 的身份运行该命令,我们需要将其用户帐户的名称传递给 sudo
命令。
sudo -u maryq /home/maryq/other-user.sh

这次脚本报告进程所有者是 maryq。
让我们在“other-user.sh”脚本中添加一行。我们将 echo
一些文本并将输出重定向到名为“mary.txt”的文件中。
#!/bin/bash
echo "Script name:" $0
echo "Working directory:" $(pwd)
echo "Script running as user:" $(whoami)
echo "This is going into a file in /home/maryq/" > /home/maryq/mary.txt
我们正在 Mary 的主目录中创建新文件。这很好,因为我们以 Mary 的身份运行脚本。
./other-user.sh

如果我们查看 Mary 的主目录,我们会看到该文件已创建,并且该文件的所有权属于 maryq 用户帐户。
ls -hl mary.txt

如果 Mary 自己实际启动了脚本,我们会看到同样的行为。
运行用户命令
您可以使用我们目前在脚本中使用的 sudo -u
命令,但还有另一个命令 runuser
,它旨在以不同的用户身份从内部运行进程脚本。它可以更好地处理启动进程的返回代码,并且比 sudo
的开销更少。
runuser
命令需要由 root 运行,但这是通过以 root 身份运行整个脚本来完成的。您不需要在脚本中使用 sudo
。 runuser
命令也可以在命令行上使用,因此不限于脚本使用,尽管它是脚本的首选方法。
Dave 无法列出“mary.txt”文件,因为它位于 Mary 的主目录中,而他无权访问。
cat /home/maryq/mary.txt

但是,我们可以使用 runuser
查看文件内部。 -
(登录)选项启动一个新的 shell,其环境与 Mary 实际登录后的 shell 环境非常接近。-c
(命令)选项后面是我们要运行的命令。
sudo runuser - maryq -c 'cat mary.txt'

请注意,该命令不需要文件的完整路径。我们可以用与 Mary 相同的方式引用该文件,相对于她的主目录。
作为用户 Dave,我们将创建一个名为“run-maryq.sh”的脚本,其中包含以下文本:
#!/bin/bash
runuser -l maryq -c 'cat mary.txt'
我们将使它可执行:
chmod +x run-maryq.sh

让我们看看当我们尝试运行它时会发生什么。
./run-maryq.sh

runuser
命令会报错,因为它是由普通用户执行的。让我们用 sudo
再次运行它。
sudo ./run-maryq.sh

这就像我们希望的那样工作,就好像玛丽自己启动了脚本一样。
使用哪一个?
在命令行上,它们之间没有太多选择。但是,由于无论如何您都必须将 sudo
与 runuser
一起使用,因此您最好单独使用 sudo
。
但在脚本中,runuser
是首选命令。