我做了一个简单的bash脚本,需要在整个脚本中保持超级用户权限。 不幸的是,当sleep
发生时,该脚本失去了sudo
权限。 对我不好:
sudo echo "I am sudo!" # Asks for passwords sleep(60) sudo echo "I am sudo!" # Need to enter password again.
我考虑用一个让sudo活着的while循环替代sleep
,但是我确定有更好的选项可以让sudo
许可保持在整个脚本中?
谢谢
sudo的灵活性被广泛低估了。 这导致了很差的做法(如sudo su -
canon球手术方法)。
一个更好的方法是在不使用密码的情况下明确允许你打算允许的命令 :
phill = NOPASSWD: /bin/ls, /usr/bin/lprm
您可以选择为特定用户从特定管理员用户运行的特定主机执行此操作。 您甚至可以阻止用户将shell转义作为参数传递。 你可以让sudo阻止启动的程序动态地执行更多的应用程序等等。你将需要阅读sudoers的man页面(并且一定要阅读编辑这个特殊文件的过程!) 。
这里有一些小事情,( 从这里 ):
User_Alias OPERATORS = joe, mike, jude Runas_Alias OP = root, operator Host_Alias OFNET = 10.1.2.0/255.255.255.0 Cmnd_Alias PRINTING = /usr/sbin/lpc, /usr/bin/lprm OPERATORS ALL=ALL #The users in the OPERATORS group can run any command from any terminal. linus ALL=(OP) ALL # The user linus can run any command from any terminal as any user in the OP group (root or operator). user2 OFNET=(ALL) ALL # user user2 may run any command from any machine in the OFNET network, as any user. user3 ALL= PRINTING # user user3 may run lpc and lprm from any machine. go2linux ALL=(ALL) ALL # user go2linux may run any command from any machine acting as any user. (like Ubuntu) If you want not to be asked for a password use this form go2linux ALL=(ALL) ALL NO PASSWD: ALL
您可以通过添加到/ etc / sudoers来调整此超时
Defaults timestamp_timeout=#Number of minutes
但是运行起来要容易得多
sudo ./worker.sh
这是一个解决方法:
sudo echo "I am sudo!" # Asks for passwords ( while true; do sudo -v; sleep 40; done ) & # update the user's timestamp sudoPID=$! # ... sleep(60) sudo echo "I am sudo!" # Need to enter password again. kill -TERM $sudoPID sudo -k # invalidate the user's timestamp at end of script (does not require a password)
这我的方式:
#!/bin/sh echo "Working..." # add you pass echo "yourpass" >> file.pass ;sleep 5 # Check if root if [ `cat file.pass | sudo -S su root -c whoami` != "root" ]; then echo "Not running as root. Exiting..." sleep 2 echo "Cleaning..." sleep 1 srm file.pass echo "Cleaned" exit 0 else echo "Running as root. Good" sleep 2 # and run any sudo with cat file.pass | sudo -S su root -c ls #<any command> fi sleep 5 echo `cat file.pass | sudo -S su root -c whoami` "say bay bay" # if pass no longer need srm file.pass echo "End session :)" exit 0
严格地在脚本中工作(而不是编辑sudoers文件或通过sudo ./script.sh
调用脚本),这里是我认为最干净的方法。
startsudo() { sudo -v ( while true; do sudo -v; sleep 50; done; ) & SUDO_PID="$!" trap stopsudo SIGINT SIGTERM } stopsudo() { kill "$SUDO_PID" trap - SIGINT SIGTERM sudo -k }
基本上,这定义了一对启用和禁用sudo模式的功能。 在运行使用sudo的代码之前调用startsudo
,使用sudo进行身份验证,fork一个后台sudo刷新循环,保存循环PID,并设置一个信号陷阱,以便在按Ctrl + C时停止sudo模式。 调用stopsudo
杀死循环,清除信号陷阱,并使以前的认证与sudo无效。
将这些函数复制到你的脚本后,像这样使用它们。
startsudo echo "Sudo mode is active." # whatever you want to do with sudo stopsudo
我要感谢@karl简单的说明了sudo-refreshing循环,@sehe指出如果信号陷阱没有被正常杀死,应该使用信号陷阱来杀死循环。 这两个想法都改进了我的btrfs备份脚本 ,它使用sudo-refreshing循环来避免在子卷的备份花费的时间超过sudo的超时时间后重新提示用户。
全部获得root权限:
sudo su - # What I need to do with root