如何在 Bash 中按小时超时(并且即使会话关闭也保持超时)?

如何在 Bash 中按小时超时(并且即使会话关闭也保持超时)?

我创建了以下脚本来在 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

对于多个命令,您有两种选择:

  1. 组合echo命令:

    (echo "command1"
     echo "command2"
     echo "command3" ) | at + 2 hours
    
  2. 使用临时文件作为命令列表:

     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 工具)以确定经过的时间段(不是已测试)。

相关内容