著者:シェルスクリプトマガジン編集部 松浦智之
会議室にはホワイトボードがあり、机の傍らにはメモ用紙がある。人はそこに、図や文字を書いたり消したりを繰り返すことで、考えを整理する。なぜなら人は、短期記憶の領域が狭いため、考察対象となる物事はホワイトボードや紙等に書き出しておかないと処理しきれないからだ。
そこは、人が創り出したコンピューターも似ている。一定以上の情報はCPU上に置いておけないため、メモリに変数という形で書き出し、それより大きいものはディスクにファイルという形で書き出しながら処理をする。特にUNIX では、ファイルを活用すると上手くいくようにデザインされている。
ところが、POSIX にはその、ホワイトボードやメモ用紙に相当する一時ファイル(テンポラリーファイル)を作るコマンドがない。何も考えずもちろん作るだけなら簡単なのだが、セキュリティーを確保しながら作るには一工夫がいる。今回は、一時ファイル作成時に必要なセキュリティーについて学び、これをPOSIXで実現する。
記事本文掲載のシェルスクリプトマガジンvol.45は以下リンク先でご購入できます。
1 2 |
dir=${TMPDIR:-} [ -d "${TMPDIR:-}" ] || dir='/tmp' |
1 2 3 4 |
file=$(cat /dev/urandom | dd count=1 bs=8 2>/dev/null | od -A n -t x1 | tr -d ' ' ) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# ディレクトリー名を決める dir=${TMPDIR:-} [ -d "${TMPDIR:-}" ] || dir='/tmp' dir=${dir%/} # 一時ファイル生成ループ(最大3 回試行) retry=2 while [ $retry -ge 0 ]; do # ファイル名を決める file=$(cat /dev/urandom | dd count=1 bs=8 2>/dev/null | od -A n -t x1 | tr -d ' ' ) # 安全に配慮して生成してみる (set -C ; umask 177 ; : > "$dir/$file") 2>/dev/null # 成功していたらループ脱出 case $? in 0) break;; esac # 失敗していたファイル名を消して再試行 file='' retry=$((retry-1)) done # 成功時→ファイル名表示 失敗時→エラー終了 case "$file" in '') echo 'Failed' 1>&2; exit 1;; *) echo "$dir/$file" ;; esac |
mktempコマンドをPOSIX原理主義で書き直したものを作りました。
https://github.com/ShellShoccar-jpn/misc-tools/blob/master/mktemp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
#! /bin/sh ############################################# # 初期設定 ############################################# # 始めに、一時ディレクトリーを安全に作る tmp=`mktemp -d -t "${0##*/}.XXXXXXXXXXXX"` || exit 1 # 各種ディレクトリー設定 datd=/home/URIAGE_KANRI/DATA # 本日日付 today=$(date '+%Y%m%d') ############################################# # 商品マスターから価格マスターを作る ############################################# cat $datd/SHOHIN_MASTER.TXT | # 1:商品ID 2:商品名3:価格 self 1 3 | sort -k 1,1 > $tmp-kakakumst ############################################# # 今日の総売り上げ計算する ############################################# cat $datd/URIAGE_$today.TXT | # 1:時刻2:所品ID 3:売れ数 self 2 3 | # 1:所品ID 2:売れ数 sort -k 1,1 | join1 key=1 $tmp-kakakumst | # 1:所品ID 2:価格3:売れ数 lcalc '$2 * $3' | # 1:商品毎の小計 | sm2 0 0 1 1 > $datd/TOTAL_$today.TXT ############################################# # 終了 ############################################# rm -rf "$tmp" exit 0 |