web-dev-qa-db-ja.com

60分間実行した後、Linuxサーバーをシャットダウンするにはどうすればよいですか?

セキュリティ上の理由から、通常はオフになっているサーバーがあります。作業したいときは、スイッチを入れてタスクを実行し、再度シャットダウンします。私のタスクは通常15分以内に完了します。 60分後に自動的にシャットダウンするメカニズムを実装したいと思います。

私はcronでこれを行う方法を調査しましたが、サーバーが最後にオンにされたときにcronが考慮に入れていないので、それが適切な方法であるとは思いません。周期的なパターンしか設定できませんが、そのデータは考慮されません。

どうすればこの実装を実行できますか?

18
jmhostalet

毎回同じユーザーとしてタスクを実行する場合は、オプションでオプション-Pを指定してシャットダウンコマンドをプロファイルに追加するだけです。数値は、シャットダウンコマンドが遅延する分数を表します。ユーザーがパスワードなしでSudoを介してシャットダウンコマンドを実行できることを確認してください。

echo "Sudo shutdown -P +60" >> ~/.profile
23
Dirk Krijgsman

いくつかのオプションがあります。

  • shutdown -Pに直接時間を提供してください:

    shutdown -P +60
    

    shutdownman page も指摘することに注意してください:

    Time引数を使用すると、システムが停止する5分前に/ run/nologinファイルが作成され、それ以上のログインが許可されないようになります。

  • at コマンドを使用します。

  • systemdユニットファイル または initスクリプト 起動時にshutdown -P 60を実行します。

  • 起動後にコマンドを実行するには、cronの @reboot を使用します。

    (ルート)crontabに追加:

    @reboot shutdown -P +60
    

最後の2つの方法では、shutdownに時間引数を使用する代わりにsleep 3600 && shutdown -P nowを使用して、シャットダウンを60分間遅らせることもできます。このようにして、シャットダウンが発行される前の最後までログインできます。

69
sebasth

これは XY問題 のように見えます。

私のタスクは通常15分以内で終わります。 60分後に自動的にシャットダウンするメカニズムを実装したいと思います。

60分後にシャットダウンすると、特に複雑な問題が発生し、さらに時間が必要になるというリスクがあります。以前のソリューションの多くは、シャットダウンを遅らせることを容易にしません。

タスクがインタラクティブタスクではなく、代わりに別のマシンから自動的にトリガーされるスクリプトタスクである場合、@ sdkksは すばらしい解決策 を与えました。スクリプトとそのすべてのタスクが終了したらすぐに、マシンにpoweroffを実行するようにタスクを実行する必要があります。

ただし、タスクがインタラクティブタスクである場合は、代わりにアイドル検出を行うことをお勧めします。

GUI(X11)でタスクを実行する場合、ここで説明するアプローチを使用してアイドルGUIセッションを検出できます:システムがアイドル状態で、再びアクティブになったときにコマンドを実行します

端末からタスクを実行する場合は、whoコマンドを使用して、ログインしているユーザーを検出できます。 whoが空の結果を返した場合にマシンをシャットダウンするcronjobを設定できます。これはかなり保守的なアプローチになることに注意してください。コンソールを接続したままアイドル状態にした場合、システムはシャットダウンされません。

もう少しアグレッシブになり、アイドルターミナルセッションも切断したい場合は、以前のアプローチを アイドルSSHセッションの自動切断ClientAliveIntervalおよびClientAliveCountMaxと組み合わせることができます。 SSHがなくてもローカルターミナルセッションがある場合の別のアプローチは、wコマンドで返されるターミナルidle時間を使用することです。

33
Lie Ryan

ここでの以前の回答はすべて完璧への要件を満たしていますが、タスクが完了したらすぐにマシンの電源を切ることもできます。

bashスクリプトはtrappedにすることができます。つまり、特定のシグナルを傍受し、必要に応じて特定のタスクを実行できます。 EXITは、トラップできる信号の1つです。

次のことができます。

  1. 自動化シェルスクリプトのtrapEXITに設定します。これは、自動化タスクの終了を意味します
  2. .bashrctrapEXITを設定します。つまり、そのマシンからログアウトするたびに、電源を切ります。

オプション#1は、タスクがアドホックインスペクションと手動の判断を必要としない限り、理想的なケースです。

オプション#2は、電源をオフにせずに端末を終了するのを忘れた場合をカバーします。ただし、注意点があります。同じマシンへの複数のターミナルが開いていて、そのうちの1つを終了した場合でも、マシンの電源はすべてオフのままです。 (それを回避するためにスクリプト化することができますが、私は解決策を複雑にしません。)

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

これは、オプション#2の.bashrcの最後、オプション#1のスクリプトの上部のどこかにあります。

スクリプトの最後にpoweroffを使用しないのはなぜですか?

スクリプトの上部にset -eo pipefailを使用することを好みます。エラーが発生しても、黙って失敗することはありません。それ以上のコマンドの実行を停止します。 trap of EXIT信号は、エラーが原因でスクリプトが途中で終了するケースをカバーする必要があります。

ただし、タスクによっては、完了する前にマシンがシャットダウンすることもあります。

スクリプトをデバッグしやすくするために使用するシンプルなbashテンプレートがあります。多分それはいくつかの役に立つかもしれません。 this Gist を参照してください。

8
sdkks

以下は、パラメータを使用してcommandを実行します。正常に完了すると、ユーザーがpoweroffを実行できると想定して、ボックスがすぐにオフになります。 Sudo poweroffを使用する必要がある場合があります。

command --parameters && poweroff

これに対して、次のコマンドは、コマンドが終了するとただちにpoweroffを実行します。

command --parameters ; poweroff

コマンドの完了後に残り時間が必要だと思われる場合は、次を実行します。

command --parameters ; sleep 3600 ; poweroff

コマンドが残業する可能性があると思われる場合は、1時間に制限できます。

timeout 1h command --parameters ; poweroff

timeoutcoreutilsパッケージの一部であるため、おそらくすでにお持ちです。

5
Criggie

@dirktコメントについて詳しく説明すると、.bashrcまたは.profile、またはログイン時にシェルが使用するファイルにatコマンドを挿入して、ログインの60分後に自動シャットダウンをスケジュールできます。

何かのようなもの:

at now + 60 minutes -f /sbin/halt
5
Mr Shunz

セキュリティについて本当に心配している場合は、電源に機械式コンセントタイマーを使用してください。シャットダウンする時間に設定してください。この方法では、誰もリモートでログインしてシャットダウンを無効にすることはできません。物理的なアクセスが必要になります。

3
gogators

systemdマシンを使用している場合は、 単調タイマーを使用できます

タイマーユニット/etc/systemd/system/shutdown_after_an_hour.timer

[Unit]
Description=shutdown after an hour

[Timer]
OnBootSec=1h

[Install]
WantedBy=timers.target

タイマーユニット/etc/systemd/system/shutdown_after_an_hour.service

[Unit]
Description=shutdown after an hour

[Service]
ExecStart=/sbin/poweroff --force --no-wall
Type=oneshot

それは

# systemctl enable shutdown_after_an_hour.timer

そのステータス(特にシャットダウンまでの残り時間)は、

# systemctl list-timers shutdown_after_an_hour.timer

次回の再起動時に機能しますが、systemctl startセッションが作成されたときに機能しない(再起動中にトリガーされなかったため)か、1時間経過した場合はすぐにマシンをシャットダウンするため、セッション中に作成されます。実際にどちらが発生するのかはわかりません。その特定のケースをテストしたことはありません。

2
WoJ

スクリプト(Sudo shutdown -P 3600)を/etc/init.dディレクトリに配置して、起動時に自動的に実行するようにしてください。

または、anacronを使用して、/etc/anacrontabファイルにコマンドを追加します。また、コマンドの前にNohupを使用して、ログアウト後もコマンドが機能していることを確認することをお勧めします。

1
Saveriofr

シェルのログアウトファイルを活用する

UIDによって開始されるインタラクティブタスクまたは非インタラクティブタスクのサーバーのみが必要な場合は、シャットダウンコマンドを〜/ .bash_logoutファイルに入れることを検討してください。 GNU Bash Manual はこう言っています:

対話型ログインシェルが終了するか、非対話型ログインシェルがexit組み込みコマンドを実行すると、Bashは〜/ .bash_logoutファイル(存在する場合)からコマンドを読み取って実行します。

したがって、「Sudo poweroff」などをログアウトファイルに追加すると、サーバーの電源がオフになりますログアウトするとすぐに現在のセッション、または非インタラクティブなBashセッションがexitを呼び出したとき。シャットダウンを延期したい場合は、atを使用するか、shutdownに時間遅延を渡すこともできます。

これをよりインタラクティブに行うには、次のバシズムをログアウトファイルに追加します。

# Shutdown unless N or n is pressed within 30 seconds.
shopt -s nocasematch
read -t 30 -N 1 -p 'Shutdown now? (Y/n) '
[[ "$REPLY" =~ n ]] || Sudo poweroff

注意事項

このソリューションについては、いくつかの注意点があります。

  • これは、X Windowsで起動された端末でも機能する可能性がありますが、startxなどで起動されなかったX11セッションでは機能しない可能性があります。
  • exitを呼び出す非インタラクティブなスクリプトがある場合、予期しないシャットダウンが発生する可能性があります。
  • シャットダウンコマンドにNOPASSWDを指定していない場合、またはシャットダウンコマンドを実行する前にSudo -vを呼び出していない場合、sudoersファイルはパスワードを要求する場合があります。
  • 私がまだ考えていない他のEdgeのケースがおそらくあるでしょう。

つまり、このアプローチが実際のニーズを満たしているかどうか、またはログインしているユーザーの不在を監視するなど、まったく別のアプローチの方が適しているかどうかを検討する必要があります。あなたの走行距離は間違いなく異なります。

1
CodeGnome