以另一个用户身份从没有 tty stdin 的 root 脚本运行脚本

以另一个用户身份从没有 tty stdin 的 root 脚本运行脚本

使用 CentOs,我想以用户“training”的身份运行一个脚本作为系统服务。我使用 daemontools 来监控该进程,它需要一个以 root 身份运行且没有 tty 标准的启动器脚本。

下面我给出了五次不同的尝试,但均失败了。

  1. #!/bin/bash
    exec >> /var/log/training_service.log 2>&1
    setuidgid training training_command
    

    最后一行还不够好,因为对于 training_command,我们需要为训练用户设置环境。

  2. su - training -c 'training_command' 
    

    看起来像这样(以不同用户身份运行 shell 脚本),但给出 ' standard in must be tty' 作为 su,确保 tty 存在,以便可能接受密码。我知道我可以通过修改 /etc/sudoers 来让它消失(a lahttps://superuser.com/questions/119376/bash-su-script-giving-an-error-standard-in-must-be-a-tty) 但我不太情愿,而且不确定后果会怎样。

  3. sudo -u training -i bash -c 'source $HOME/.bashrc; training_command'
    

    同一主题的变奏:' sudo: sorry, you must have a tty to run sudo'

  4. runuser - training -c 'training_command'  
    

    这给出了runuser: cannot set groups: Connection refused。我发现这个错误没有任何意义或解决办法。

  5. ssh -p100 training@localhost 'source $HOME/.bashrc; training_command'
    

    这更像是一个笑话,用来表达绝望。甚至这个也失败了Host key verification failed.(主机密钥在known_hosts中,等等)。

注意:如果我从根 shell 运行包装器脚本,那么 2、3、4 均能正常工作。仅当系统服务监视器(daemontools)启动它时才会出现问题(我猜没有 tty 终端)。

我陷入了困境。这件事真的很难实现吗?

我感谢所有关于最佳实践的见解和指导。

(这也已在超级用户上发布:https://superuser.com/questions/434235/script-calling-script-as-other-user

答案1

您需要禁用forrequiretty中的设置。通过添加以下行:/etc/sudoersrootvisudo

Defaults:root !requiretty

您还需要以下行/etc/sudoers才能root完成所有操作(这应该默认启用,但请检查以确保):

root ALL=(ALL) ALL

然后您可以执行以下操作:

sudo -u training /path/to/training_command

答案2

这似乎本质上是一个特殊情况这个问题;我们可以用来伪造一个 tty。唯一的问题是,出于某种原因,script -c我无法直接使用该技巧,而且如果您真的必须在之前进行源代码处理,那么它就有点难看了。尝试:susudo~/.bashrctraining_command

echo password | script -c "sudo su - training -c training_command" 

答案3

选择第一个并设置所需的环境变量。

如果您已经使用过 daemontools,那么您就不需要手动创建或处理日志文件了。Daemontools 会为您完成这项工作。

这是应用程序运行脚本

#!/bin/bash
exec 2>&1
exec setuidgid training sh -c 'YOURVARIABLE=yourvalue exec training_command'

然后创建一个log具有其自己的运行脚本的目录运行脚本。

请参阅此条目来设置日志: http://cr.yp.to/daemontools/faq/create.html#runlog

答案4

在SSH下,你可以foo.sh以普通用户身份运行命令:

$ ssh [email protected] bash /path/to/foo.sh

如果某个foo.sh命令需要 root 权限,例如,netstat,则将其包装在su命令中,如下所示(替换原始的netstat -tunple):

su -c "netstat -tunpl" root

foo.sh并像这样运行:

$ ssh -t [email protected] bash /path/to/foo.sh

这将提示两个密码,第一个是normal_user,第二个是root

相关内容