![如何在 Bash 中按小时超时(并且即使会话关闭也保持超时)?](https://linux22.com/image/101580/%E5%A6%82%E4%BD%95%E5%9C%A8%20Bash%20%E4%B8%AD%E6%8C%89%E5%B0%8F%E6%97%B6%E8%B6%85%E6%97%B6%EF%BC%88%E5%B9%B6%E4%B8%94%E5%8D%B3%E4%BD%BF%E4%BC%9A%E8%AF%9D%E5%85%B3%E9%97%AD%E4%B9%9F%E4%BF%9D%E6%8C%81%E8%B6%85%E6%97%B6%EF%BC%89%EF%BC%9F.png)
我创建了以下脚本来在 Ubuntu 16.04 上安装然后卸载 PHPmyadmin...
我的目标是每次我想使用 PHPmyadmin 时都使用这个脚本,然后,在一段时间之后2小时, 删除它。这安装-使用-卸载使用该方法是出于安全原因(尽可能保持MySQL不可访问并且仅在很短的时间内在本地访问)。
bash /dev/fd/15 15<< 'EOF0'
#!/bin/bash -x
# Install commands:
sudo apt-get install phpmyadmin
sudo phpenmod mcrypt
sudo phpenmod mbstring
cat << EOF1 >> /etc/apache2/apache2.conf
Include /etc/phpmyadmin/apache.conf
EOF1
sudo service apache2 restart
# Unnstall commands:
sleep 2h
sudo phpdismod mcrypt mbstring
sudo apt-get purge phpmyadmin
sudo service apache2 restart
sed -i 's/Include \/etc\/phpmyadmin\/apache.conf/ /g /etc/apache2/apache2.conf
EOF0
正如杰夫(以及我编辑代码示例时)的评论中所指出的,我可以使用该sleep
命令,但是sleep
,以其经典形式要求会话保持打开状态,并且窗口有时可能会因任何原因关闭,因此这是一个规范的答案需要展示如何给予这 2 小时的暂停,但以这样的方式,即使我错误地/故意关闭了窗口,或者我的电脑因任何原因重新启动,或者停电了 --- 暂停和之后的所有命令它将继续在 VPS 上运行,不受我端的任何干扰。
那么,如何在安装命令 2 小时后以与会话无关的方式执行卸载命令?
答案1
您可以使用该实用程序来实现它at
。
对于单个命令,请执行以下操作:
at 'now + 2 hours' -f /path/to/uninstall.sh
对于多个命令,通过以下方式将脚本提供给 shellcat heredocument:
cat << EOF | at 'now + 2 hours'
command1
command2
........
EOF
或者,您可以通过systemd
解决方案来实现这一点(同样,如果您安装了它)
systemd-run --on-active=2h -- /bin/bash /path/to/uninstall.sh
答案2
正如我所看到的,您可以sudo
访问并可以启动服务。因此,您可以使用atd
服务和at
命令来安排您的任务:
echo 'touch $HOME/`date -j +%s`.txt' | at + 2 minutes
对于多个命令,您有两种选择:
组合
echo
命令:(echo "command1" echo "command2" echo "command3" ) | at + 2 hours
使用临时文件作为命令列表:
tmp_file=$(mktemp --tmpdir uninstall_commands.XXXX) echo "command1" >> ${tmp_file} echo "command2" >> ${tmp_file} echo "command3" >> ${tmp_file} at -f ${tmp_file} + 2 hours rm -f -- ${tmp_file}
答案3
假设有两个脚本(做一件事;做得好):
安装.sh
#!/bin/sh -eu
sudo apt-get install phpmyadmin
sudo phpenmod mcrypt mbstring
printf 'Include /etc/phpmyadmin/apache.conf' >> /etc/apache2/apache2.conf
sudo service apache2 restart
卸载.sh
#!/bin/sh -eu
sudo phpdismod mcrypt mbstring
sudo apt-get purge phpmyadmin
sudo service apache2 restart
sed -i 's/Include \/etc\/phpmyadmin\/apache.conf/ /g /etc/apache2/apache2.conf
我能想到的最简单的答案正是你想要的
./install.sh && sleep 2h && ./uninstall.sh >>/var/log/mylog.log 2>&1
其中每个脚本还包含一个用于连接到服务器的 ssh 命令。这种方法对服务器电源循环具有弹性,但对终端机则不然。
作为替代方案,我会简化这个答案主要是因为 atd 放置输出的奇怪行为,而是使用
nohup sleep 2h && ./uninstall.sh >>/var/log/mylog.log 2>&1 &
执行后,您现在有大约 2 小时的时间来做您想做的任何事情,时间到了后,卸载过程就会发生。这种方法不能适应服务器电源循环。
这个答案避免了依赖性,并通过明智地捕获和记录相关输出来实现诊断/调试。
答案4
我不确定这个解决方案是否能满足您的要求,但您可以尝试一下。
如果暂时忘记了 PC shutdown/reboot ,那么以下命令可以在 bash 中运行而不会捕获终端(您可以尝试将其作为一行命令进行测试):
sleep 10 && yad --text="10 seconds passed" && exit &
上面的命令,尽管我没想到会这样,即使我关闭终端窗口也能工作。
PS:如果将其与 nohup 结合使用,即使您注销,命令也会保持运行。
作为解决方法,您可以将初始脚本拆分为两个较小的脚本;一个用于安装的脚本,一个用于删除的脚本,如下所示:
#script_to_install.sh
sudo apt-get install phpmyadmin
sudo phpenmod mcrypt mbstring
printf 'Include /etc/phpmyadmin/apache.conf' >> /etc/apache2/apache2.conf
sudo service apache2 restart
sleep 7200 && path/to/script_to_remove.sh &
exit #exit the first script to free terminal (or even close the terminal)
#end of script_to_install.sh
#script_to_remove.sh
#Optionally you can use xterm -e (or similar) to bring up a terminal window automatically to see the output of the commands
sudo phpdismod mcrypt mbstring
sudo apt-get purge phpmyadmin
sudo service apache2 restart
sed -i 's/Include \/etc\/phpmyadmin\/apache.conf/ /g /etc/apache2/apache2.conf
exit
#end of script_to_remove.sh
回到 PC 重新启动部分,我认为这可以通过将开始时间写入临时日志文件来解决,一旦重新启动,您可以监视该临时文件(即使用 inotify 工具)以确定经过的时间段(不是已测试)。