cleanup(){
# Do some tasks before terminating
echo oh la la, cleaning is so nice
echo "See you later, world"
sudo poweroff & # finally shutdown
}
trap cleanup EXIT
这可以在.bashrc选项 #2 的末尾,在选项 #1 的脚本顶部的某个位置。
为什么不在poweroff脚本末尾使用?
set -eo pipefail我更喜欢在我的脚本顶部使用at。如果发生任何错误,它不会静默失败;它将停止执行更多命令。trapof EXITsignal 应涵盖脚本由于错误而过早终止的情况。
有几个选项。
直接提供时间
shutdown -P
:请注意,
shutdown
手册页还指出:使用
at
命令。创建一个在启动时运行的systemd 单元文件或初始化脚本
shutdown -P 60
。启动后使用 cron
@reboot
运行命令。添加到(根)crontab:
对于最后两种方法,您也可以使用
sleep 3600 && shutdown -P now
而不是使用 time 参数shutdown
来延迟关机 60 分钟。这种方式可以在发出关机前的最后一刻登录。这看起来像一个XY 问题。
如果您在 60 分钟后关闭,您可能会遇到可能遇到特别复杂的问题并且需要更多时间的风险。以前的许多解决方案都不容易延迟关机。
如果任务不是交互式任务,而是从另一台机器自动触发的脚本任务,@sdkks 提供了一个很好的解决方案;你真的应该让机器在脚本及其所有任务完成后立即运行 poweroff。
但是,如果您的任务是交互式任务,我建议改为进行空闲检测。
如果您在 GUI (X11) 中执行任务,则可以使用此处描述的方法检测空闲 GUI 会话:Run a command when system is idle and when is active again
如果您通过终端执行任务,则可以使用该
who
命令检测登录用户。who
您可以设置一个 cronjob,如果返回空结果则关闭机器。请注意,这将是一种相当保守的方法;如果您让控制台保持连接状态,它不会关闭系统,而是处于空闲状态。如果您想更积极一点并断开空闲的终端会话,您可以将之前的方法与自动断开空闲的 SSH 会话
ClientAliveInterval
和ClientAliveCountMax
. 如果您没有 SSH,但有本地终端会话,则另一种方法是使用命令返回的终端空闲时间w
。如果您每次都以同一个用户的身份执行任务,您可以简单地将关闭命令(可选的 -P 选项)添加到您的配置文件中。该数字代表关闭命令延迟的分钟数。确保您的用户无需密码即可通过 sudo 执行关机命令。
添加:
在阅读了大多数其他答案后,我喜欢在(root)cron 中添加“@reboot /<path to script/command>”的选项。sebasth 给出的答案是他的第四个选项。您可以添加关闭命令或编写一个小脚本来执行关闭并通过 cron 执行。如果您使用 systemd,WoJ 也有一个很好的解决方案。
虽然这里之前的答案都满足完美的要求,但是你也可以在任务完成后立即关闭你的机器。
bash
脚本可以被trap
ped,这意味着某些信号可以被拦截,某些任务可以在需要时执行。EXIT
是可以捕获的信号之一。您将能够:
trap
为您的自动化 shell 脚本设置一个EXIT
,这意味着您的自动化任务的终止trap
为您的设置一个.bashrc
EXIT
,这意味着每当您注销该机器时,将其关闭。选项 #1 将是理想的情况,前提是您的任务不需要临时检查和人工判断。
选项 #2 将涵盖您忘记在未关闭电源的情况下退出终端的情况。不过有一个警告;如果您打开了同一台机器的多个终端并且您从其中一个退出,它仍然会关闭机器的电源。(可以编写脚本来避免这种情况,但我不会使解决方案复杂化。)
这可以在
.bashrc
选项 #2 的末尾,在选项 #1 的脚本顶部的某个位置。为什么不在
poweroff
脚本末尾使用?set -eo pipefail
我更喜欢在我的脚本顶部使用at。如果发生任何错误,它不会静默失败;它将停止执行更多命令。trap
ofEXIT
signal 应涵盖脚本由于错误而过早终止的情况。但是,对于您的任务,这也可能意味着机器将在完成之前关闭。
我有一个简单的
bash
模板,用于使脚本更易于调试;也许它可能会有一些用处。请参阅此要点。以下是
command
带参数运行的,如果成功完成,它将立即关闭盒子,假设用户可以运行poweroff
. 它可能需要使用sudo poweroff
.而以下
poweroff
命令在命令终止时立即运行:如果您认为命令完成后需要休息时间,请运行
如果您认为该命令可能会超时运行,您可以将其限制为一个小时:
timeout
是coreutils
包装的一部分,因此您可能已经拥有它。详细说明@dirkt 评论,您可以在您的或您的 shell 在登录时使用的任何文件上插入一个
at
命令,以安排在您登录后 60 分钟自动关闭。.bashrc
.profile
就像是:
如果您真的担心安全性,请在电源上使用机械插座计时器。只需将其设置为您希望它关闭的任何时间。这样,没有人可以远程登录并禁用关机。您将需要物理访问。
尝试将脚本 (
sudo shutdown -P 3600
) 放在/etc/init.d
目录中以在启动时自动运行它。或者尝试使用
anacron
,在/etc/anacrontab
文件中添加命令。我还建议nohup
在命令前面使用,以确保该命令在注销后仍然有效。如果您在
systemd
机器中,则可以使用单调计时器定时器单元
/etc/systemd/system/shutdown_after_an_hour.timer
定时器单元
/etc/systemd/system/shutdown_after_an_hour.service
:它通过启用
其状态(特别是在关机前还剩多少时间)可通过以下方式获得
它将在下一次重新启动时工作,在
systemctl start
创建它的会话期间对它没有用,因为它要么不起作用(因为它在重新启动期间未触发),要么在超过一小时后立即关闭机器。事实上,我不知道会发生哪一个,我从未测试过那个具体案例。利用 Shell 的注销文件
如果您只需要服务器执行由您的 UID 启动的交互式或非交互式任务,请考虑将您的关闭命令放入您的~/.bash_logout文件中。GNU Bash 手册说:
因此,在注销文件中添加“sudo poweroff”或类似内容会在您注销当前会话或非交互式 Bash 会话调用时立即关闭服务器
exit
。如果您希望推迟关机,您还可以选择使用at或通过延时关机。对于一个更具交互性的方法,您可以将以下 Bashisms 放入您的注销文件中:
注意事项
关于此解决方案,您应该牢记一些注意事项:
startx
或类似启动的 X11 会话。exit
,您可能会遇到意外的关闭。NOPASSWD
关闭命令,或者sudo -v
在运行关闭命令之前没有调用,您的 sudoers 文件可能会提示输入密码。简而言之,您可能需要考虑这种方法是否满足您的实际需求,或者是否采用完全不同的方法(例如监视登录用户的缺失或其他替代方法)是更好的选择。您的里程肯定会有所不同。