问题
crontab中使用sudo切换用户执行命令sudo -u user command
时,会报sudo: sorry, you must have a tty to run sudo
的错误。
原因
在一些Linux发行版中,会默认设置运行sudo
需要在tty中运行。以CentOS 7.0为例,在/etc/sudoers
中, 有一个默认设置Defaults requiretty
。
1 2 3 4 5
| # # Disable "ssh hostname sudo <cmd>", because it will show the password in clear. # You have to run "ssh -t hostname sudo <cmd>". # Defaults requiretty
|
解决方案
如下提供两个解决方案:
修改/etc/sudoers
修改/etc/sudoers
,注释掉Defaults requiretty
。事实上,红帽已经在最新版本的RedHat和Fedora中移除了该默认配置,详细讨论可以参照Bug 1020147。比如在CentOS 7.6.1810中,已经没有了requiretty
的默认设置。
改为使用su -c
可以使用su
来替换sudo
来运行命令。su user -c "command"
实验
设置Defaults requiretty时
使用root用户,在crontab中设置如下任务
1 2 3
| * * * * * echo "`date`" >> /tmp/root_echo.txt 2>&1 * * * * * sudo -u deployer echo "`date`" >> /tmp/deployer_echo.txt 2>&1 * * * * * su deployer -c "echo \"`date`\"" >> /tmp/deployer_su_echo.txt 2>&1
|
隔两分钟后查看/tmp
下的对应文件。
1 2 3 4 5 6 7 8 9 10 11 12 13
| [root@localhost tmp]# tail -n 10 /tmp/*echo*.txt ==> /tmp/deployer_echo.txt <== sudo: sorry, you must have a tty to run sudo sudo: sorry, you must have a tty to run sudo ==> /tmp/deployer_su_echo.txt <== Thu Jun 25 17:54:02 CST 2020 Thu Jun 25 17:55:01 CST 2020 ==> /tmp/root_echo.txt <== Thu Jun 25 17:54:02 CST 2020 Thu Jun 25 17:55:01 CST 2020 [root@localhost tmp]#
|
可以看到:
- 直接
echo
可以执行成功.
sudo -u deployer command
执行失败,会报错误sudo: sorry, you must have a tty to run sudo
。
su deployer -c command
的形式可以成功执行。
去除Defaults requiretty时
使用root用户,在crontab中设置如下任务
1 2 3
| * * * * * echo "`date`" >> /tmp/root_echo.txt 2>&1 * * * * * sudo -u deployer echo "`date`" >> /tmp/deployer_echo.txt 2>&1 * * * * * su deployer -c "echo \"`date`\"" >> /tmp/deployer_su_echo.txt 2>&1
|
隔两分钟后查看/tmp
下对应的文件。
1 2 3 4 5 6 7 8 9 10 11 12 13
| [root@localhost tmp]# tail -n 10 /tmp/*echo*.txt ==> /tmp/deployer_echo.txt <== Thu Jun 25 18:02:02 CST 2020 Thu Jun 25 18:03:01 CST 2020 ==> /tmp/deployer_su_echo.txt <== Thu Jun 25 18:02:02 CST 2020 Thu Jun 25 18:03:01 CST 2020 ==> /tmp/root_echo.txt <== Thu Jun 25 18:02:02 CST 2020 Thu Jun 25 18:03:01 CST 2020 [root@localhost tmp]#
|
可以看到,三种形式都可以执行成功。
延伸
/etc/sudoers
中Defaults requiretty
的配置,也会影响使用ssh
命令的执行。
去除Defaults requiretty时
去除Defaults requiretty时,使用ssh加sudo命令,可以直接执行成功。
在Mac上执行ssh + command
1 2 3 4
| $ ssh root@192.168.187.181 'sudo -u deployer echo "hello, world" >> /tmp/hello.txt' root@192.168.187.181's password: $
|
在Linux上可以看到/tmp/hello.txt的内容
1 2 3
| [root@localhost tmp]# cat /tmp/hello.txt hello, world [root@localhost tmp]#
|
设置Defaults requiretty时
设置Defaults requiretty时,直接使用ssh加sudo命令,会报错。
在Mac上执行ssh + command
1 2 3 4
| $ ssh root@192.168.187.181 'sudo -u deployer echo "hello, world. -- with default requiretty" >> /tmp/hello.txt' root@192.168.187.181's password: sudo: sorry, you must have a tty to run sudo $
|
此时,会报sudo: sorry, you must have a tty to run sudo
的错误。
在ssh时候,加上-t参数,参数显式的告诉 ssh,我们需要一个 TTY 远程 shell 进行交互,命令就可以成功执行。
1 2 3 4
| $ ssh -t root@192.168.187.181 'sudo -u deployer echo "hello, world. -- with default requiretty" >> /tmp/hello.txt' root@192.168.187.181's password: Connection to 192.168.187.181 closed. $
|
再查看Linux上/tmp/hello.txt
的内容,可以看到刚echo的内容hello, world. -- with default requiretty
成功被写入了文件。
1 2 3 4
| [root@localhost tmp]# cat /tmp/hello.txt hello, world hello, world. -- with default requiretty [root@localhost tmp]#
|
Reference