コマンドラインからモノスペースのメールを送る
Linuxのshellからモノスペースのメールを送る方法を調べましたので記しておきます。
- Debian 12
メールのContent-Type
をtext/html
にし、コンテンツを<html><pre></pre></html>
で囲むとモノスペースになります。
なぜモノスペースにしたいか
Linuxのmail
コマンドは標準入力をメール本文として送ることができる手軽なコマンドです。例えば、以下のようにして本文Helloをrootに送ることができます。
echo Hello | mail -s 'Greeting' root
しかしながら、このメールはプレインテキストであるため、ほとんどのMUAはプロポーショナルフォントで本文を表示します。人間が書く文章ならそれでいいのですが、コマンド出力をメールで送る場合は不都合があります。例えば、df
コマンドがそれです。
df | mail -s 'Greeting' root
df
コマンドは端末がmonospaceであることを仮定してテキストにフォーマットをかけています。しかし、プレインテキストのメールとして送ると、MTAではフォーマットが崩れます。たとえば、Gmailで受信するとこのようになります。
これでは読みにくいため、モノスペースを送る側で強制したいというのが動機です。
モノスペースのメールを送る
モノスペースのメールを送るには
- コンテンツにHTMLタグを付加して
- メールヘッダに
text/html
を指定
する必要があります。
HTMLタグの付加
送りたいコンテンツの前後にHTMLタグを付加します。これはecho
コマンドでできます。
(echo '<html><pre>' ; df; echo '</pre></html>')
()
はサブシェルです。サブシェル内で実行したプログラムの標準出力はひとつにまとめられます。結果的にecho
, df
, echo
プログラムの出力が順番にサブシェルの標準出力として出てきます。
これでコンテンツ側は終わりです。
メールヘッダの付加
メールヘッダを追加してtext/html
を指定するには、mail
コマンドの-a
オプションを使います。例えば、rootに送るのであれば。
mail -s 'Subject' -a 'Content-Type: text/html' root
とします。
結果
以上を組み合わせると、コマンドは以下のようになります。
(echo '<html><pre>' ; df; echo '</pre></html>') | mail -s 'monospace mail' -a 'Content-Type: text/html' root
Gmailでこのメールを受け取ると、
となり、モノスペースで表示されているとわかります。
応用
モノスペースのメールがレポートとして読みやすいことを利用して、cronから定期的にコンピュータの情報を遅らせる使い方があります。
比較的シンプルな例
例えば、SSDの状態を週に一度レポートしたいときには、
sudo crontab -e
を実行して、エディタの中で次の一行を追加します。
0 0 * * 1 ( echo '<html><pre>' ; df; echo; free; echo; /sbin/smartctl -A -H /dev/nvme0n1; /sbin/nvme error-log /dev/nvme0 -e 1 ; echo '</pre></html>' ) | mail -s 'Physics server health report' -a 'Content-Type: text/html' root
これで、毎週月曜日の午前0時に以下のプログラムの実行結果がモノスペースのメールで送られてきます。メール本文を組み立てる部分を行単位にばらすと以下のようになります。
echo '<html><pre>'
df
echo
free
echo
/sbin/smartctl -A -H /dev/nvme0n1
/sbin/nvme error-log /dev/nvme0 -e 1
echo '</pre></html>'
もっと複雑な例
以下はかなり複雑なcrontabの例です。
0 0 * * 1 ( echo '<html><pre>' ; df; echo; free; echo; /sbin/smartctl -A -H /dev/nvme0n1; /sbin/nvme error-log /dev/nvme0 -e 1 ;echo; ( typefile=`mktemp`; tempfile=`mktemp`; cat /sys/class/thermal/thermal_zone*/temp > "$tempfile" ; cat /sys/class/thermal/thermal_zone*/type > "$typefile"; paste "$typefile" "$tempfile" | column -t | sed 's/\(.\)..$/.\1℃/'; rm "$typefile" "$tempfile" ); echo '</pre></html>' ) | mail -s 'Physics server health report' -a 'Content-Type: text/html' root;
先の例と同じように本文を組み立てる部分を行単位にばらすとこうなります。
echo '<html><pre>' ;
df;
echo;
free;
echo;
/sbin/smartctl -A -H /dev/nvme0n1;
/sbin/nvme error-log /dev/nvme0 -e 1 ;
echo;
(
typefile=`mktemp`;
tempfile=`mktemp`;
cat /sys/class/thermal/thermal_zone*/temp > "$tempfile";
cat /sys/class/thermal/thermal_zone*/type > "$typefile";
paste "$typefile" "$tempfile" \
| column -t \
| sed 's/\(.\)..$/.\1℃/';
rm "$typefile" "$tempfile";
);
echo '</pre></html>'
/sbin/nvme
コマンドまでは最初の例と同じです。
paste
コマンドはふたつのファイルを連結するコマンドです。cat
コマンドが列を重ねる(垂直)方向で連結するのに対して、paste
コマンドは行を重ねる(水平)方向に連結します。
paste
コマンドが連結しているのは、/sys
ファイルシステムにあるプロセッサの温度センサー名type
とその値temp
です。この結果はcolumn
コマンドに送られて人間が読みやすいように表形式に整えられます。最後に、sed
コマンドで温度の値(ミリ度単位)を整形して読みやすい表示にしています。
送られてきたメールから温度の部分だけ抜粋すると以下のようになります。
acpitz 30.0℃
pch_cannonlake 30.0℃
x86_pkg_temp 36.0℃
履歴
- 2025/Feb/24 : 応用における、crontabの設定を修正。曜日を1に変更。曜日の指定が0だったため、メールを全く送らない設定だった。
- 2025/Mar/17 : 応用に複雑な例を追加。その後、ファイルの削除忘れを修正。
Discussion