Linuxコマンド・bashの使い方実例

Linuxコマンド・bashの使い方の実例を紹介します。
管理人は現役ITエンジニアとして働いております(本業は組み込み系)。
かれこれ10年以上ITエンジニアとしてのキャリアを積んできました。
まだまだ未熟者ですが、皆さんのお役に立てたら幸いです。

カテゴリ: Linuxコマンド

mailxコマンドを使ってメールを受信する方法と、コマンドラインからのメールの読み方を解説します。
シェルスクリプトからメールを読み出す方法とその実例も載せます。
なお、メールの送信方法については触れませんが、既に解説しているこちらのページを参照してください。

.mailrcにIMAPサーバー設定をする

メールを受信するための事前準備として、IMAPサーバーの設定をします。
IMAPサーバーとは、メールを受信するサーバーのことで、利用するメールサービスごとに読み替えて設定してください。
ここでは、Gmailを例として設定します。

.mailrcの内容:
set folder=imaps://username@imap.gmail.com
set password-username@imap.gmail.com="yourpassword"
set imap-use-starttls
こちらのページにあるメールを送信する際の設定が.mailrcに残っている場合、後ろに続けて上記の内容を追記してください。
ピンクの網掛けの部分が、メールサービスや個人ごとに異なる部分です。
username の箇所は、Googleアカウント名になります(メールアドレスの@より前の文字)。
yourpassword の箇所は、Googleアカウントのパスワードになります。
パスワードをファイルに残す際は、パーミッションを600へ変更しましょう。具体的には、.mailrcの編集が終わったら、以下のコマンドを実行してください。
chmod 600 .mailrc
こうすることで、所有者以外の閲覧権限が無くなります。
なお、これらの設定値はメール送信の時にも説明しましたが、-Sオプションを使ってコマンドラインで指定することも可能です。

メールを受信する

メールを受信するには、次のコマンドを実行します。
mailx
非常にシンプルですが、これだけです。
mailxコマンドは、何のオプションも指定しなかった場合、メール閲覧モードになります。
IMAPサーバからメール情報を取得するため、しばらく時間がかかる可能性があります。
メールの受信に成功すると、以下のような画面が出力されます。これをメールヘッダのリストといいます。古いメールから順に表示されます。
この画面が表示されていれば、メールの受信は成功しています。
もし、メールボックスにメールが1通も無い場合は、「No mail for username」と表示されます。
Heirloom mailx version 12.5 6/20/10.  Type ? for help.
"imaps://zundoko77@imap.gmail.com/INBOX": 51222 messages 43567 unread
 U27141 ****************** Tue Dec 26 19:13     /17451 **********************
 U27142 ****************** Tue Dec 26 19:21     /42500 **********************
 U27143 ****************** Tue Dec 26 19:22     /39320 **********************
 U27144 ****************** Tue Dec 26 20:02     /17168 **********************
>F27145 ****************** Tue Dec 26 20:17     /11386 **********************
 O27146 ****************** Tue Dec 26 20:45     /18150 **********************
 O27147 ****************** Tue Dec 26 22:09     /16809 **********************
 O27148 ****************** Tue Dec 26 22:17     /14216 **********************
 U27149 ****************** Wed Dec 27 06:13     /31113 **********************
 U27150 ****************** Wed Dec 27 06:12     /13376 **********************
 U27151 ****************** Wed Dec 27 08:14     /18321 **********************
 U27152 ****************** Wed Dec 27 09:03     /50992 **********************
 U27153 ****************** Wed Dec 27 09:10     /17965 **********************
 U27154 ****************** Wed Dec 27 10:08     /18437 **********************
 U27155 ****************** Wed Dec 27 11:23     /10103 **********************
 O27156 ****************** Wed Dec 27 11:23     /13267 **********************
 U27157 ****************** Wed Dec 27 11:28     /18004 **********************
 U27158 ****************** Wed Dec 27 12:30     /17333 **********************
 U27159 ****************** Wed Dec 27 13:02     /10499 **********************
 U27160 ****************** Wed Dec 27 13:03     /11346 **********************
?

メールを読む

メールを読むには、?と出ているプロンプトに続けて、次のコマンドを実行します。
t
このtは、typeの省略で、typeと打っても構いません。また、print(p)でも構いません。
tだけだと、ヘッダのリストでカーソル「>」があたっているメールを読みます。
プロンプトが「:」に変わっていれば、エンターを入力することで続きを読むことができます。
このモードを抜けるには、qを打ちます。そうすると、プロンプトは再び「?」になります。
ヘッダのリストに表示されている任意のメールを読みたい場合は、tの後ろに、ヘッダのリストの先頭にある番号を指定します。ただし、UやOなどのアルファベットは含みません。
t27141
再びヘッダのリストを表示させるには、次のコマンドを実行します。
h
ヘッダのリストを移動させるには、次のコマンドを実行します。
z
「z-」とすることで、後ろに移動する(戻す)こともできます。
また、最新メールのヘッダリストを表示するには、次のコマンドを実行します。
h$
最新メールから読みたい場合は、特によく使うコマンドです。
なお、zやhの後ろにつける「-」や「$」は、edコマンドの用法に基づいており、
+は次、-は前、$は一番最後、*は全てを意味します。

シェルスクリプトでメールを読む例

上記のメールを読む方法は、ターミナルから対話式でメールを読む方法でした。
では対話式ではないスクリプトでは、メールを読むことができるのでしょうか。
スクリプトの場合、以下のように書くことでメール内容を表示することができます。
#!/bin/sh
echo "t$" | mailx
スクリプトで実行する場合は、対話式で使うコマンドをパイプ「|」でmailxコマンドに渡します。
そうすることで、コマンドの実行結果を取得することができます。
なお上記のスクリプトの場合、最新メールの内容を、標準出力に表示して終了します。
typeコマンドに最後を意味する$を指定することで、一番最後に受信したメール、すなわち最新メールを表示するという処理になります。

もう一つ例を挙げます。
以下のようにすることで、メールの内容をファイルに出力することができます。
#!/bin/sh
echo "w (from username@hotmail.co.jp) test.txt" | mailx
この例では、writeコマンド(w)を使用しています。writeコマンドは、条件に合うメールの本文だけを、指定されたファイル(test.txt)に出力します。今回はこの条件を、username@hotmail.co.jpという差出人からのメールを対象にしました。(from mail_address)とすることで、差出人を条件にすることができます。
このスクリプトを実行すると、username@hotmail.co.jpからのいくつかのメールの本文を、test.txtへ出力します。

これさえできれば、あとはメール記載内容を判別するなどして、あらゆる処理に応用できるでしょう。
例えば、「メール本文にABCという文字列が含まれていれば、Xという処理を実行する」などが考えられます。

メールを読む時のコマンド

これまでにいくつか挙げましたが、メールを読む時に様々なコマンドを指定することが可能です。
以下にいくつか説明しますが、他にも多くのオプションがあります。もっと深く知りたい場合はマニュアルページ(次のコマンドを実行:man mailx)を参照してください。

プロンプトが?の時に実行できるコマンド:
h #ヘッダのリストを表示
from mail_address #mail_addressからのメールを一覧表示。
p #メールを表示
r #指定したメールの全員に返信
w 1 test.txt #番号1のメールをtest.txtに保存
? #コマンドの簡単な要約を表示
q #終了
条件の指定:
. #今指定しているメール
$ #最後(最新)のメール
^ #最初(最古)のメール
* #全てのメール
1-5 #範囲指定。番号1から5までのメールを対象
(from mail_address) #差出人を指定
(to username) #宛先を指定
(subject string) #件名を指定
/string #全てのメールの件名からstringを含むメール
ちなみに、mailxを処理するマシンによっては、これらコマンドの実行に時間がかかる場合がありますので、コマンドの実行結果が返って来ない場合は気長に待ちましょう。

スポンサードリンク
このエントリーをはてなブックマークに追加
スポンサードリンク

RaspberryPiやUbuntuなどのLinux環境において、スクリプトからメールを送信する方法を紹介します。
この方法では、postfixなどでMTAを構築せずとも、メールを送信することができます。
なお、メールを受信する方法ついてはこちらのページで解説しています。

前提:
・ここで紹介する方法は、Ubuntu、Raspbianで確認しました。その他のOS、ディストリビューションで正しく動作するかは未確認です。
・メール受信の方法についてはここでは紹介しません。こちらのページを参照ください。
・使用するSMTPサーバの認証方式によっては、ここで紹介する.mailrcの設定以外に、必要な項目がある可能性があります。ここでは楽天メールを使用した場合の一例に留めます。
(2021/02/07追記)Gmailの例も追記しました。

mailxコマンドのインストール:
メールを送るために、mailxコマンドを使用します。
mailxコマンドを使うことで、MTAを構築せずに、直接SMTPサーバへメールを転送することができます。
以下のコマンドでmailxコマンドをインストールしてください。
sudo apt-get install heirloom-mailx
なお、既にインストールされているかどうかは、下記のコマンドで確認してください。
sudo dpkg -l | grep mailx
ii  heirloom-mailx                        12.5-4                                    armhf        feature-rich BSD mail(1)
上記のように、 heirloom-mailx が出力された場合は、インストール済みなので不要です。

.mailrcの作成:
 スクリプトを実行するユーザーのホームディレクトリ(~)に、.mailrcを作成します。
内容は下記の通りです。
vim ~/.mailrc ←vimエディタで作成。viでもnanoでも何でも良いです。
.mailrcの内容:
set smtp=smtp://mail.gol.com:587
set from=xxxxxxx@gol.com
set smtp-auth-user=xxxxxxxx@gol.com
set smtp-auth-password="xxxxxxxx"
set smtp-use-starttls

(2021/02/07追記)Gmailの場合、.mailrcの内容は以下となります。
SMTPS(SMTP over SSL/TLS)を使う場合:
set smtp=smtps://smtp.gmail.com:465
set from=xxxxxxx@gmail.com
set smtp-auth-user=xxxxxxx@gmail.com
set smtp-auth-password="xxxxxxx"
STARTTLSを使う場合:
set smtp=smtp://smtp.gmail.com:587
set from=xxxxxxx@gmail.com
set smtp-auth-user=xxxxxxx@gmail.com
set smtp-auth-password="xxxxxxx"
set smtp-use-starttls

※注意※
Gmailの場合、安全性の低いアプリの許可をオフにしていると、認証で拒否されてしまい、メールを送ることができません(デフォルトでオフになっているため注意)。
こちら(Googleのサイト)を参照し、安全性の低いアプリの許可をオンにしてください。
これはGoogleがOAuth2.0という認証方式を推奨しているためで、現状mailxコマンドではOAuth2.0の認証を行うことができません。
mailxは開発が終了しており、s-nailというコマンドが現在活発に開発されているようなので、今後そちらでOAuth2.0に対応するかもしれません。続報があればまたこの記事を更新したいと思います。

.mailrcの解説:
これらの設定値は各メールサービスによって異なるので、利用するメールサービスごとに読み替えて設定してください。
set smtp=smtp://mail.gol.com:587
送信メール(SMTP)サーバの指定と、通信ポートの指定。
利用する送信元サーバーの暗号化通信方式によって指定が異なります。
この例の場合だと、暗号化通信方式がSTARTTLSという方式であり、587ポート(サーバによって異なる場合あり)を指定しています。
Gmailの場合は、SMTPS(SMTP over SSL/TLS)という方式もサポートしており、SMTPS(SMTP over SSL/TLS)を使う場合は smtps://と、sを付けてサーバーの指定を行い、ポート番号は465を指定します。
また、STARTTLSを利用する場合は、.mailrcに以下の指定を追加します。
set smtp-use-starttls
この指定をしなければ、以下のようなエラーメッセージが出て送信できない場合があります(これもサーバ側のセキュリティ機能です)。
smtp-server: 530 5.7.0 Must issue a STARTTLS command first.

set from=xxxxxxx@gol.com
送信元メールアドレス

set smtp-auth-user=xxxxxxxx@gol.com
SMTP認証のユーザ名。サーバーにもよりますが、一般的にはメールアドレスです。

set smtp-auth-password="xxxxxxxx"
SMTP認証のパスワード。
パスワードをファイルとして残すのに懸念がある場合は、以下のように-Sオプションを使うことでコマンドラインで指定することも可能です。
mail -s "SUBJECT" -S smtp-auth-password="xxxxxxxx" xxxxxxxx@hotmail.co.jp </home/hoge/msg.txt



メール送信:
ここまでで準備は完了したため、あとはメールを送るだけです。
以下のコマンドでメールを送信してください。
mailx -s "SUBJECT" xxxxxxxx@hotmail.co.jp < /home/hoge/msg.txt

SUBJECTがメールの件名です。
xxxxxxxx@hotmail.co.jpが宛先メールアドレスです。
/home/hoge/msg.txtの中身が本文です。

本文をファイルから入力しない場合、以下のようにパイプで渡すこともできます。
echo "HONBUN" | mailx -s "SUBJECT" xxxxxxxx@hotmail.co.jp

また、件名、宛先、本文を指定しなければ、対話モードでメールを作成します。この時、件名、宛先を入力した後のEnterで何も表示されなければ、本文入力の開始です。本文の入力の終了はCtrl+Dを入力します。

スクリプトでメールを作成する場合は、本文をテキストファイルで出力しておいて、mailxコマンドの入力にすることが多いでしょう。この時、cronなどでmailxコマンドを実行する場合は、ファイルの入出力は絶対パスで指定しないと、相対パスで意図しないパスを見てファイル入出力が正しく行われなかったりするので、気をつけましょう。
このエントリーをはてなブックマークに追加

ログファイルなどでファイルが増え続ける場合、
最新ファイルは残し、古いファイルは随時削除したい場合があります。

以下のスクリプトは、指定されたディレクトリにあるファイルの中から、
引数に指定された新しいファイルの数分を残し、他のファイルを削除するスクリプトです。

■スクリプト本体
こちらよりダウンロードできます。

ファイル名:
delete_old.sh

使い方:
第一引数に、残す最新ファイルの数を指定し、
第二引数に、削除対象のファイルが含まれるディレクトリを指定してください。

例:
./delete_old.sh 3 /test/log
この場合、/test/logに含まれるファイルのうち、最新の3ファイルを残し、他を削除します。
ただし、ディレクトリは削除されません(エラーが出て削除さない)。

※注意※
誤ってファイルを削除しないよう、ダウンロードしたままでは、ファイルは削除されません。
削除対象のファイルは、「delete ~」のようなログで表示されます。
動作に問題が無いことを確認したうえで、11行目のコメント(#)を削除して、削除処理を有効にしてください。


■スクリプト処理解説
#!/bin/bash
所謂おまじない。どのシェルを使って処理をするかの指定をする。

FILE_LIST=`ls -t $2`
第二引数に指定されたディレクトリに含まれるファイルを、更新日時が新しい順で、変数FILE_LISTに代入する。

count=0
count変数に0を代入(変数初期化)。

for FILE in $FILE_LIST
FILE_LISTに含まれるファイル名を、順にFILE変数に代入する繰り返し。FILE変数に入れるファイルが無くなった時、この繰り返し処理を抜ける。

do
        ((count++))
count変数に1を加算(インクリメント)。

echo "check $FILE"
「check  FILE変数の内容」というログをコンソールに出力する。

if [ $count -gt $1 ]; then
if条件分岐。count変数が、第一引数に指定された数よりも大きい時、次のfiまでの間の処理を実行する

#rm $FILE
FILE変数のファイルを、削除する(削除処理を有効にする場合、#を削除してください)。
なお、rmに-rオプションを追加することで、ディレクトリも削除することができます。
ここでは、ディレクトリを誤って削除しないよう、あえてオプションを付けていません。

echo "delete $FILE"
「delete FILE変数の内容」というログをコンソールに出力する。

fi
if条件分岐の終了。

done
繰り返し処理の先頭に戻る。もう一度for~の処理を実行する。

echo "finish"
「finish」という文字列を出力する。

■補足
こういった処理は、自動で定期的に実行されるべきです。
削除処理をスクリプトで自動化したとはいえ、スクリプトを実行するのが手動では、手間がかかることに変わりはありません。
cronを設定することで、定期的に勝手に実行されることができるようになります。
是非cronの設定をして自動化をしましょう。
cronの設定方法は別の記事で解説したいと思います(記事にでき次第、ここにリンクを載せます)。

このエントリーをはてなブックマークに追加

Linux環境での圧縮・解凍コマンドをまとめました。
圧縮プログラムが多いので、忘れやすいですよね。

※以下の表はディレクトリごと圧縮する場合を想定して記載しています。
 targetが圧縮するディレクトリ名、target.zip(.tar .tgz .tar.xz .tbz .tlz)が圧縮・解凍するファイル名です。

拡張子ごとの圧縮方法と解凍方法まとめ表
拡張子圧縮方法解凍方法
.zipzip -r target.zip target/unzip target.zip
.tartar -cvf target.tar target/tar -xvf target.tar
.gz .tar.gz .tgztar -cvzf target.tgz target/tar -xvzf target.tgz
.xz .tar.xztar --xz -cvf target.tar.xz target/tar --xz -xvf target.tar.xz
.bz2 .tar.bz2 .tbztar -cvjf target.tbz target/tar -xvjf target.tbz
.lz .tlztar --lzip -cvf target.tlz target/ (*1)tar --lzip -xvf target.tlz

*1 以下のようなエラーが発生した場合、
 lzipがインストールされていない可能性があります。
 tar (child): Error is not recoverable: exiting now
 lzipをインストールする方法:sudo apt-get install lzip

■解説
zip以外はtarコマンドを使います。
zipの-rオプションは、ディレクトリを圧縮する場合に指定します。
以下はtarコマンドのオプションの説明です。
-c 圧縮する場合に指定します。(createのcと覚えましょう)
-x 解凍する場合に指定します。(extractのxと覚えましょう)
-v 情報を出力します。指定しなくても動作します。
-f 後続のファイルが圧縮ファイル名示します。ファイル名の直前でなければなりません。順番をいれかえると意図しない動作になるため注意(例えば-cfvにすると、vという名の圧縮ファイルが生成されます)。
-z gzipプログラムで圧縮する場合に指定します。
--xz(または-J) xzプログラムで圧縮する場合に指定します。
-j bzip2プログラムで圧縮する場合に指定します。
--lzip lzipプログラムで圧縮する場合に指定します。

■(参考)圧縮サイズ比較
全てテキストファイルで構成されるディレクトリを圧縮した場合、
(バイナリの場合はまた結果は変わってくると思うので、参考までに)
結果は以下となりました。
最もサイズが小さいのは、tbz(gzip2)でした。

   273  8月 30 22:45 target.tbz
   289  8月 30 22:49 target.tlz
   294  8月 30 22:44 target.tgz
   316  8月 30 22:44 target.xz
  1331  8月 30 23:02 target.zip
 10240  8月 30 23:02 target.tar



このエントリーをはてなブックマークに追加

業務では、あるファイルに対する変更を、別のファイルにも適用する機会が多くあります。
こういった単純作業は、自動化して(パッチを当てて)一瞬で終わらせてしまいましょう。

ここでは、diffコマンドで作成したパッチを、patchコマンドで適用する方法を紹介します。


■パッチ(差分ファイル)を作成する

diff -ru [変更前ディレクトリ] [変更後ディレクトリ] > patch_work

解説:
変更前にディレクトリごとバックアップをとっておいたことを前提として、
ディレクトリ単位で差分patch_workに出力します。

rオプションは、サブディレクトリに含まれるファイルも再帰的に比較するために指定します。

uオプションは、差分をユニファイドdiff形式で出力するために指定します。

patch_workにリダイレクト(>)で出力していますが、ファイル名は何でも構いません。


■パッチを当てる

patch -u  -p 1 -d [パッチを当てるディレクトリ] < patch_work

解説:
uオプションはユニファイドdiff形式のパッチを当てる場合に指定します。

pオプションは、パッチファイルに記載されているファイルパスの階層を無視する数を指定します。

この例だと、-p 1と指定しているため、パッチファイルに記載されているファイルパスが
src_dir/test.txt と記載されている場合、1階層分のsrc_dirが無視され、
カレントディレクトリにあるtest.txtとしてpatchコマンドは認識します。

pオプションを指定する理由は、次のdオプションを使うためです。

dオプションの意味は、
「指定されたディレクトリへ移動してpatchコマンドを実行する」という意味です。

このように、pオプションとdオプションを組み合わせることで、
パッチに記載されているディレクトリ名と、パッチを当てたいディレクトリ名が異なる場合でも、パッチを当てることができます。
少しわかりにくいかもしれませんが、実際にコマンドを実行してみると理解できると思います。

patchコマンドを実行すると、SuccessやFailerなどの文字が出力されます。
これは、パッチが正しく「当たった」か、「当たらなかった」かを表しています。
パッチが「当たらなかった」時は、当たらなかったファイルの同階層に、
.rej拡張子のファイルが出力されます(ファイルの検索は目視ではなくfindコマンドを使用しましょう)。
このファイルに、当たらなかった差分が出力されているので、
手動でその差分を目的のファイルにマージしてください。

なお、パッチが「当たらない」場合とは、
パッチに記載されている差分の前後3行に一致する行が無かった場合か、
逆に一致する行が複数あってどこに当てるべきか判断できない場合などです。
対処として、パッチの作成時に前後の出力する行数をUオプションなどで調整したりします。


解説は以上です。
私の説明が下手でわかりにくいかもしれませんが、
たった2つのコマンドしか実行していません。

非常によく使う、強力なコマンドですので、
Linuxを使う方はぜひ活用し、作業を効率化しましょう。

このエントリーをはてなブックマークに追加

↑このページのトップヘ