Crontab中解决sorry, you must have a tty to run sudo的方法
问题
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 | # |
解决方案
如下提供两个解决方案:
修改/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 | * * * * * echo "`date`" >> /tmp/root_echo.txt 2>&1 |
隔两分钟后查看/tmp下的对应文件。
1 | [root@localhost tmp]# tail -n 10 /tmp/*echo*.txt |
可以看到:
- 直接
echo可以执行成功. sudo -u deployer command执行失败,会报错误sudo: sorry, you must have a tty to run sudo。su deployer -c command的形式可以成功执行。
去除Defaults requiretty时
使用root用户,在crontab中设置如下任务
1 | * * * * * echo "`date`" >> /tmp/root_echo.txt 2>&1 |
隔两分钟后查看/tmp下对应的文件。
1 | [root@localhost tmp]# tail -n 10 /tmp/*echo*.txt |
可以看到,三种形式都可以执行成功。
延伸
/etc/sudoers中Defaults requiretty的配置,也会影响使用ssh命令的执行。
去除Defaults requiretty时
去除Defaults requiretty时,使用ssh加sudo命令,可以直接执行成功。
在Mac上执行ssh + command
1 | $ ssh root@192.168.187.181 'sudo -u deployer echo "hello, world" >> /tmp/hello.txt' |
在Linux上可以看到/tmp/hello.txt的内容
1 | [root@localhost tmp]# cat /tmp/hello.txt |
设置Defaults requiretty时
设置Defaults requiretty时,直接使用ssh加sudo命令,会报错。
在Mac上执行ssh + command
1 | $ ssh root@192.168.187.181 'sudo -u deployer echo "hello, world. -- with default requiretty" >> /tmp/hello.txt' |
此时,会报sudo: sorry, you must have a tty to run sudo的错误。
在ssh时候,加上-t参数,参数显式的告诉 ssh,我们需要一个 TTY 远程 shell 进行交互,命令就可以成功执行。
1 | $ ssh -t root@192.168.187.181 'sudo -u deployer echo "hello, world. -- with default requiretty" >> /tmp/hello.txt' |
再查看Linux上/tmp/hello.txt的内容,可以看到刚echo的内容hello, world. -- with default requiretty成功被写入了文件。
1 | [root@localhost tmp]# cat /tmp/hello.txt |