The jonki

呼ばれて飛び出てじょじょじょじょーんき

プログラムの実行終了をトリガーにGmailを送る

機械学習におけるコーディングではプログラムの実行時間は長くなりがちです.機械学習時のプログラムはもちろん,データの前処理にも多くの時間がかかります.このようなプログラムを動かしている間は安心してYoutubeでも見て勉学に励みたいものです.

そこで今回はプログラム実行終了時に,自分から自分宛にGmailを送ってみるプログラムを作ってみます.メール送信にはMSMTPというSMTPクライアントを用います.Ubuntuを想定していますが,適当なLinuxでも動くはずです.

MSMTPのセットアップ

インストールは至極簡単です.

sudo apt install msmtp msmtp-mta

今回Gmailを使いたいのでGoogle アカウントのアプリパスワードにてmsmtp用の16桁のパスワードを発行してください.発行ができたら下記のファイルを作ってください.from, user, passwordは適宜変更してください.

cat ~/.msmtprc
# Set default values for all following accounts.
defaults
auth           on
tls            on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile        ~/.msmtp.log

# Gmail
account        gmail
host           smtp.gmail.com
port           465
tls_starttls   off
from           your.name@gmail.com
user           your.name
password       abcd efgh ijkl aaaa


# Set a default account
account default: gmail

これで下記のように実行してメールが送られていれば成功です.前者は本文だけ,後者はタイトル付きです.

echo "hello world." | msmtp your.name@gmail.com
echo -e "Subject: AAA\n\nhello" | msmtp your.name@gmail.com

いろいろな使い方

これだけでも十分便利になりそうですが,もうひと工夫してみましょう.

本文だけ or タイトル&本文だけ渡して実行できるようにする

PATHの通った場所にスクリプトを置きます.これは適宜好きなものにしてください.

sudo touch /usr/local/bin/email
sudo chmod 700 /usr/local/bin/email
sudo chown you:you /usr/local/bin/email

プログラム( /usr/local/bin/email )は下記のようにしてみました.引数が1つのときは本文のみ,2つのときはタイトルと本文,というコマンドになります.

#!/bin/bash

RECIPIENT="your.name@gmail.com"

if [ "$#" -eq 2 ]; then
    SUBJECT=$1
    BODY=$2
elif [ "$#" -eq 1 ]; then
    SUBJECT="My Notification"
    BODY=$1
else
    echo "Usage: $0 'Description' [Title]"
    exit 1
fi

# メール送信
echo -e "Subject: $SUBJECT\n\n$BODY" | msmtp "$RECIPIENT"

確認してみましょう.2行まとめてターミナルに貼り付けて実行してください.

# wget終わったらメール送信する
# 本文だけ
wget "http://www.google.com" 
email "test content"

# タイトルと本文
wget "http://www.google.com" 
email "test title" "test content"

実行中のプロセスが終わったらメール送信する

実行時に今回のコマンドを渡していればよいですが,実行中のプログラムに対して終わったら知りたいな,という時もよくあります.無理やりその実行中のプログラムのpane上で上記のコマンドを送っておく,というのも手だとは思います.しかし今回は,プロセスを監視してそのプロセスが消えたときにメールを送信するプログラムにしてみます.これを pidwatcher と呼ぶことにします.

pidwatcherpidwatcher <PID>とscreenやtmuxの別paneで実行しておきます,そのプロセスがなくなり次第,実行コマンドが本文になってメール送信が行われるので便利です.PIDはps等で特定してください.

#!/bin/bash

# Check if a PID is provided as an argument
if [ $# -eq 0 ]; then
    echo "Usage: $0 PID"
    exit 1 
fi

PID=$1 # Set the PID from the first argument

# Check if the process exists
if ! kill -0 $PID 2>/dev/null; then
    echo "Process does not exist: PID $PID"
    exit 1
fi

echo "Monitoring process $PID... "

# Attempt to get the command line of the process
CMDLINE=$(cat /proc/$PID/cmdline 2>/dev/null | tr '\0' ' ')

# Monitor the process until it ends
while kill -0 $PID 2>/dev/null; do
    sleep 1
done

echo "Process with PID $PID has ended. Command was: $CMDLINE"
email "Process with PID $PID has ended." "Command was: $CMDLINE"

この使い方のバリエーションとして,pidwatcher <PID> &とすれば,バックグラウンドで動いてくれます.またpidwatcher <PID> <このPIDが終わったら実行したいプログラム>とすれば今のプログラムの実行終了を待ってから次のコマンドが実行されます. ただエラー処理などはないのでご注意ください.

まとめ

今回はMSMTPを使って,プログラムの実行終了をトリガーにGmailに通知メールが飛ぶプログラムを作りました.自分で作っておいてなんですが結構便利です. ちなみに今回のプログラムは95%ぐらいはChatGPTで作りました(シェルスクリプトなど癖のある言語では本当に便利ですよね).