これはなに?
誰もログインしていないときだけ shutdown
を実行するスクリプトです。
AWS(Amazon Web Service) の EC2(Elastic Compute Cloud) インスタンスを自動停止させるために作りました。
EC2のインスタンスは起動している時間で課金されるので、たとえば開発用などで誰も使わない夜中には停止させて経費を浮かせたい、ということがしばしばあります。
こういった自動停止は AWS Lambda
を使う例がよく紹介されていますが、それだと問答無用で落としてしまいます。残業して開発している人がキレないよう、あえて cron
でやることにしました。
使い方
- 以下のスクリプトを適当なところに置き、実行権限を付与する
-
root
権限のcrontab
で自動実行を設定する
私が扱っているインスタンスでは以下のようにしています。
0,30 20-23 * * * /usr/local/sbin/condhalt
※ 20:00~23:30 まで30分毎。細かな書式はQiitaの記事「cronの設定方法」が分かりやすかったです
注意
-
shutdown
の実行には root 権限が必要なので、このスクリプトも root 権限が必要です
root のcrontab
に設定すると問題が少ないと思います -
w
とshutdown
コマンドの位置を確認する
OS、ディストリビューションによってはこれらのコマンドが置かれているパスが違う可能性があるので、適宜書き換えてください
スクリプト本体
最新版
これまでのスクリプトは、仮想端末(pts)を使わずに接続しているケースを取りこぼしていたので、ログイン状態の確認に sshd を使うようにしました。(ちなみに、Visual Studio Code でSSH接続するときには pts を使いません。それで気づいたという……)
#!/usr/bin/perl
use strict;
use warnings;
my $user = 0;
open(PCMD, '/usr/bin/ps auxww |');
while ( <PCMD> ) {
$user++ if ( /sshd: [\w_\.-]+ \[priv\]/ );
}
close(PCMD);
if ( $user == 0 ) {
system('/usr/sbin/shutdown -h now');
}
古いバージョン
#!/usr/bin/perl
use strict;
use warnings;
my $user = 0;
open(PCMD, '/usr/bin/w |');
while ( <PCMD> ) {
$user++ if ( m| pts/[0-9]+ | );
}
close(PCMD);
if ( $user == 0 ) {
system('/usr/sbin/shutdown -h now');
}
今後
この方法はお手軽なので対象インスタンスが1台2台ならいいんですが、数が増えるとスクリプトを置いたり crontab
の設定をするのは面倒です。AWS Lambda
でなんとかしたいところなので、暇を見つけて作りたいと思っています。