著者:今泉 光之
日々の業務でよく使い回すちょっとしたコードの羅列を「スニペット」(断片)として用意しておくと便利です。本特集では、作業の自動化に便利であろういくつかのシェルスクリプトスニペットを紹介します。
記事本文掲載のシェルスクリプトマガジンvol.54は以下のリンク先でご購入できます。
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 40 41 42 43 44 45 46 |
#!/bin/sh # SSL証明書の有効期限をチェックして管理者に通知する # 1日数回の実施 (10:00 / 13:00 / 16:00 / 18:00) を想定している cert="${1}" host=${2:-`hostname`} check=/tmp/sslcheck-send # リミット soft=$((30 * 24 * 60 * 60)) hard=$((10 * 24 * 60 * 60)) # パラメーターチェック if [ -z "{cert}" ] then echo "Usage: $(basename ${0}) certfile [hostname]" 1>&2 exit 1 fi # 証明書から有効日を取得 limit=$(date -d "$(openssl x509 -noout -text -in {cert} | sed -n '/Not After/s/.* : ¥(.*¥).*/¥1/p')" '+%Y/%m/%d %H:%M:%S') limit_s=$(date -d "${limit}" '+%s') today=$(date -d "00:00:00" '+%Y/%m/%d %H:%M:%S') today_s=$(date -d "${today}" '+%s') current_s=$((${limit_s} - ${today_s})) current=$((current_s / (24 * 60 * 60))) if [ ${current_s} -lt 0 ] then # 証明書期限切れ notice "ホスト ${host}の SSL証明書の期限が ${limit}で終了しています。大至急更新作業をして下さい。" elif [ {current_s} -le ${hard} ] then # 証明書期限まで残り 10 日以内 notice "ホスト ${host}の SSL証明書の期限が ${limit}までです (残り {current}日 )。至急更新作業をして下さい。" elif [ ${current_s} -le ${soft} ] then # 証明書期限まで残り 30 日以内 (1日 1回通知 ) update=$(date '+%m%d') if ! [ -f {check} -a "$(cat ${check})" -eq ${update} ] then notice "ホスト ${host}の SSL証明書の期限が ${limit}まです (残り {current}日 )。更新作業をして下さい。" echo ${update} > ${check} fi fi |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#!/bin/sh target="https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX" icon="表示されるアイコン " name="表示される名前" exec > /dev/null 2>&1 notice() { curl -X POST -H 'Content-type: application/json' --data '{"text": "'"${*}"'", "icon_emoji": "${icon}", "username": "${name}" }' ${target} } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#!/bin/sh tmpfile=${TMP:-/tmp}/rdf.$$ ssh="/usr/bin/ssh" df="LANG=C df -hlP -t ext3 -t ext4" servers="サーバー 1 サーバー 2 … サーバー n" trap 'rm -rf ${tmpfile}; exit' 0 1 2 3 15 for i in ${servers} do ${ssh} ${i} ${df} | tee ${tmpfile} | awk '{ if(NR > 1) ret += $(NF-1) > '${1:-80}' } END{ exit ret; }' || notice "${i} DISK Usage Warning!¥n $(cat ${tmpfile})" done |
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 40 41 42 43 44 45 46 47 48 49 |
#!/bin/sh usage() { echo "Usage: $(basename $0) [-f][-l time] process" 1>&2 exit 255 } # パラメーターチェック if opt=`getopt fl: $*` then set -- ${opt} while [ -n "${1}" ] do case "${1}" in -f ) cmd="sh";; -l ) limit=$2 shift;; -- ) shift break;; -* ) usage;; esac shift done else usage; fi test $# -ne 1 && usage ps ax | awk -v "process=${1}" -v "limit=${limit:-100}" ' { if($5 ~ process) { gsub(/:/, "", $4); if(($4 + 0) > (limit * 100)) pid = pid " " $1 } } END{ if(pid) print "kill" pid }' | {cmd:-cat} |
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 |
#!/bin/sh source="${1}" target="$(pwd)/${2}" if true then doit() { nkf -e ${1} > ${2} } else doit() { local _wav wav=$(echo "${2}" | sed 's/m4a/wav/') faad -q "${1}" -o "${wav}" lame --quiet -h -b 192 "${wav}" "${2}" rm "${wav}" } fi cd ${source} || exit 1 find . | while read line do if [ -d "${line}" ] then mkdir -p "${target}/${line}" else doit ${line} ${target}/${line} fi done |
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 |
#!/bin/sh # バックアップ対象はホスト名を大文字にした名前でマークする # ホスト名が myhost.example.comの場合 "MYHOST"でマーク # ディレクトリー /some/directoryをバックアップする場合 /some/directory.MYHOSTを touchする # ファイル /some/fileをバックアップする場合 /some.file.MYHOSTをtouchする # ファイルを /some/fileを編集するときにオリジナルを /some/file.MYHOST にコピーしておくと # バックアップ対象になり、更に変更内容を diffなどで変更内容を容易に確認できる。 # max generation(s) max=7 # files and directories backupdir=/home/backup targetdir=${backupdir}/$(date '+%Y%m%d') latestdir=${backupdir}/latest # backup target base=$(hostname -s | tr [:lower:] [:upper:]) # prepare directories test -d ${backupdir} && test $(ls -1 ${backupdir} | wc -l) -ge ${max} && rm -rf ${backupdir}/$(ls -1 ${backupdir} | head -1) mkdir -p ${targetdir} rm -rf ${latestdir} ln -s ${targetdir} ${latestdir} find / -name "*.${base}" | sed "s!^/¥(.*¥)¥.${base}$!¥1!g" | tar -C / -cvzf ${targetdir}/${base}.tgz -T - |
1 |
top bn1 | sed -n -e '1,/^$/p' -e '/apache/p' |
1 |
ps axH | awk '/[a]pache/{ $4=""; print $0} ' | sort -k 1,1 -rn | uniq -c |
1 |
awk '{ if($7!="408"){sub(/?.*/, "", $7); u[$7]++} }END{ for(key in u) print u[key], key }' access.log | sort -nr |
1 |
awk '{ c[$1]++ }END{ for(key in c) print c[key], key }' access.log | sort -nr |