我的目标:我有一个 bash 脚本,需要以 root 用户身份运行,并且不能被普通用户(我)杀死。但是,作为普通用户,我需要能够启动该脚本(可能存在不应执行此无法杀死的脚本的情况)。
有没有什么办法可以实现它?
我想象以下工作流程:我登录到我的常规帐户,执行 bash 脚本,然后启动一个特定程序。由于该程序是从管理员帐户启动的,因此我无法终止它。
我现在的做法:我以普通用户身份登录,su admin
输入一个复杂的密码,然后以独立方式运行该程序(即使用&
)。然后我关闭终端并继续使用打开的程序,继续我的一天。
我尝试过:授予我的用户权限来执行管理员创建的脚本,但这当然使我能够在之后终止该脚本,因为我拥有该进程。我希望该进程由另一个用户拥有。
答案1
有一种方法可以使用 setuid 位来实现这一点,但不能直接实现,因为 setuid 位在 shell 脚本中会被忽略。setuid 位仅适用于二进制可执行程序,并使程序在可执行文件所有者的用户下运行。因此,如果您的脚本是二进制程序,您需要让文件归您的管理员用户所有,然后设置 setuid 位 ( chmod u+s filename
)。
对于 shell 脚本而不是二进制程序,你需要一个中间二进制程序(所谓的包装器) 运行您的脚本 - 这是它唯一要做的事情。如果您设置包装程序 setuid,那么您的脚本将在该程序内以相同的权限运行。
看着这个答案,我在其中详细解释了如何创建这样的二进制包装程序。
答案2
您可以编写一个辅助脚本,并通过 root 的 crontab 每 1 分钟执行一次。这将充当 root 和普通用户之间的桥梁。
桥梁文件
#!/bin/bash
FILENAME="/tmp/starter-file-with-unique-name"
if [ -f $FILENAME ] ;
then
/usr/bin/specific-program
rm $FILENAME
## you could do some logging here if you want
fi
现在您的常规使用只需要创建该启动文件(例如touch /tmp/starter-file-with-unique-name
)。在接下来的 60 秒内,cron 将执行bridge.sh
,它将检测启动文件,然后执行特定程序。
crontab 条目示例
* * * * * /usr/local/bin/bridge.sh
不能等 60 秒吗?
如果您希望立即启动特定程序,可以向 中添加循环bridge.sh
,例如sleep 1
。在这种情况下,root 不应每 1 分钟执行一次脚本,而应仅执行一次,也许可以@reboot
在 crontab 中使用,或者为其创建 systemd 服务。