Dominic Alves

普段何気なく利用している/tmp/var/tmp。 意識して使い分けてる方も分けてない方もいらっしゃるかと思います。 Linuxのファイルシステムとしての存在意義や、一時フォルダとしての機能を改めて意識すると 非常に便利な存在です。

/tmpと/var/tmpの違い

「/tmpと/var/tmpの違いについて述べよ」・・・インフラエンジニアの入社試験の問題に出てきそうですね。 さて単純な解答ですが、システム的なことを言えば以下あたりです。(RHEL)

/tmp /var/tmp
再起動時にファイルが削除される 再起動しても消えない
10日間アクセスが無い場合削除 30日間アクセスが無い場合削除

どちらもディレクトリ配下はtmpwatchコマンドにより監視されファイルの削除が組み込まれています。

$ cat /etc/cron.daily/tmpwatch
#! /bin/sh
flags=-umc
/usr/sbin/tmpwatch "$flags" -x /tmp/.X11-unix -x /tmp/.XIM-unix \
        -x /tmp/.font-unix -x /tmp/.ICE-unix -x /tmp/.Test-unix \
        -X '/tmp/hsperfdata_*' 10d /tmp
/usr/sbin/tmpwatch "$flags" 30d /var/tmp
for d in /var/{cache/man,catman}/{cat?,X11R6/cat?,local/cat?}; do
    if [ -d "$d" ]; then
        /usr/sbin/tmpwatch "$flags" -f 30d "$d"
    fi
done

個人的には/tmpは「見返すことのない、ファイル名も適当で良いような一時ファイル」、 /var/tmpは「また参照するかもしれない、ファイル名がある一時ファイル(sqlのdumpなど)」 として使い分けています。

ある程度ルールを持って配置しておくと後々参照する時に楽です。

ファイルを取得する時にあえて一時ディレクトリを経由させる

リモートマシンにSSHにてログインしていて、 そこで操作しているファイルを他サーバの任意のワーキングディレクトリにコピーしたいとします。

$ ssh user@192.168.33.102
$ cd /etc/httpd/
$ ls httpd.conf #このファイルを別サーバの特定のディレクトリにコピーしたい

こういった状況下の時にどのようにすれば楽でしょうか?

直接転送したいとすれば、pwdをしたのち、SSH用のIPアドレスもメモしてフルパスを入力します。

$ scp httpd.conf root@192.168.33.105:/root/project/httpd-conf-update/

ただしこの手法はやや面倒です。パスのコピーのために画面の行き来が必要ですし、 なにせ、もし何か入力ミスがあると、その場所を探すのが大変です。

この場合、まず何も考えずにとにかく/tmpへ転送をさせます。

$ scp httpd.conf root@192.168.33.105:/tmp

その後に転送先のサーバでmvをさせます。

$ cd /root/project/httpd-conf-update/
$
$ mv /tmp/h[tab]
$ mv /tmp/http.conf ./

ログインしているサーバであれば、tabキーによるパスのサジェストももちろん利用できるので、 スムーズにファイルパスを取得することが出来ます。 「/tmpディレクトリは消えても良いファイルを置いている」という前提を立てていれば、 心置きなく転送することが出来ます。

複数サーバの操作の場合、2画面以上開いて作業されている方も多いはずです。 そういった場合、とりあえず/tmpにコピーするというルールさえあれば、

たった/tmpというたった固定の4文字を打つだけで、面倒なディレクトリパス問題を 気にしないで済みます。

ローカルMacにもコピーしたい場合のお勧め手法

tmux等のsend-keysのエイリアスを予め用意し、 固定値のPATHにコピーしてしまう仕組みを作ると簡単です。 ここでのお勧めは/tmpではなく、ユーザのホームをリンク先にしてしまうことです。

~/.tmux.conf
bind R send-keys 'Ricky@192.168.33.101:/Users/Ricky/' C-m
$ scp httpd.conf [C-b R]
$
$ scp httpd.conf Ricky@192.168.33.101:/Users/Ricky/

ユーザのホームディレクトリ/Users/[Username]~/でも同値となりますので、

$ mv ~/httpd.conf .

もっと少ない文字列でとて簡単に手元にデータを持ってくることが可能です。

Macで少し生産性の上がるBashエイリアス集でも解説した、現在開いているFinderのPATHに移動するcdfコマンドと組み合わせれば、 開いているFinderディレクトリに簡単にリモートファイルを取得することが出来ます。

$ cdf
/Users/Ricky/Projects/01_Main/20140910_httpd_conf_update
$ mv ~/ht [tab]
$ mv ~/httpd.conf . #データ取得完了

シェルスクリプトとしての/tmpの存在意義

シェルスクリプトでも活用法が沢山あります。 あまり有名ではないですが、 Linuxでは実は既にデフォルトでmktempというテンポラリファイルPATHをランダムで作ってくれるとても便利な コマンドがあります。

$ mktemp
/tmp/tmp.PZ5TDqVte4

何か複数にまたがったファイルを集計したい場合、mktempを経由すれば簡単です。 任意のサーバにあるApacheのアクセスログのユニークIP数を集計してみます。

main () {
  tmp=$(mktemp)
  for server in 192.168.33.201 192.168.33.202
  do
    scp $server:/var/log/httpd/access_log.20140920 /tmp/$server
    cat /tmp/$server >>$tmp
  done

  #複数サーバのapacheログのuniq ip数の集計
  awk '{ print $1 }' $tmp | sort -u | wc -l
}

main $@

いったんファイルを取ってきて、それをcatコマンドで結合、 結合ファイルを集計するという流れです。 「集計してほしい」と依頼が到着した時に、サクッとtmpファイルにコピー、 内容を結合したものを集計して出せるとなかなか素敵です。

main () {
  tmp=$(mktemp)
  sort import_mysql_text.tsv >$tmp
}

main $@

MySQLなどの場合は予めsortされたファイルをインポートすると高速なことは有名です。 「一瞬ソートする」というアクションもmktempコマンドさえあれば心置きなく出来ます。

BashのRsync用のエイリアスとして用意する

以下のグローバルエイリアスを~/.bashrcなどに設定します。

alias -g R="| rsync -av --files-from=- . /tmp/"

「Gitファイルで差分のものだけディレクトリ構成を残して取得したい」などのリクエストの時に便利です。

$ git diff --name-only HEAD~~~ R #Rがグローバルエイリアスでパイプ&Rsyncしてくれる

上記を書き込むだけでディレクトリ構成をキープして、/tmp以下に簡単にコピー出来ます。 あとはこの記事で記載の通り、/tmpからTabによるPathのサジェストを利用して手元にコピーです。

mv /tmp/co [tab]
mv /tmp/copied_file .

最後に

たかがtmpディレクトリですが、活用出来ればなかなか強力です。 もっと便利な活用方法等ありましたら是非共有お願いします。