Bashのプログラムで、引数のないオプションと引数を共存する方法がわからなかったので、整理してみる。
現象
実際こうなって欲しかったのだが
$ ./polling.sh https://qiita.com/koara-local/items/04d3efd1031ea62d8db5
20190321-130653 | 200
20190321-130655 | 200
^C
$ ./polling.sh -i https://qiita.com/koara-local/items/04d3efd1031ea62d8db5
20190321-130700 | 200 | https://qiita.com/koara-local/items/04d3efd1031ea62d8db5
20190321-130702 | 200 | https://qiita.com/koara-local/items/04d3efd1031ea62d8db5
20190321-130704 | 200 | https://qiita.com/koara-local/items/04d3efd1031ea62d8db5
20190321-130705 | 200 | https://qiita.com/koara-local/items/04d3efd1031ea62d8db5
実際はこうなった
$ ./polling.sh -i https://qiita.com/koara-local/items/04d3efd1031ea62d8db5
20190321-125815 | N/A | -i
20190321-125816 | N/A | -i
20190321-125817 | N/A | -i
20190321-125818 | N/A | -i
どうやらオプションがパラメータとして認識されている様子。
問題の解決
問題は、getopts
の書き方だった。知らなかったが、:
が付いているのは、オプションの引数があるこをと示している。だから、今回のアプリは、引数がないので、それを取り除いた。
while getopts "ih" opt; do
case $opt in
i)
hasUrl=true
;;
h)
usage
exit 0
;;
\?)
echo "Unknown option: -${OPTARG}" >&2
exit 1
;;
esac
done
ただし、これだと、$1
を参照しても-i
になるので、shift
コマンドで$1をシフトさせる。オプションのインデックスから1を引いた分だけシフトさせる。
shift $((OPTIND -1))
全体像
# !/bin/bash
declare -i duration=1
declare hasUrl=""
declare endpoint
usage() {
cat <<END
polling.sh [-i] [-h] endpoint
Report the health status of the endpoint
-i: include Uri for the format
-h: help
END
}
while getopts "ih" opt; do
case $opt in
i)
hasUrl=true
;;
h)
usage
exit 0
;;
\?)
echo "Unknown option: -${OPTARG}" >&2
exit 1
;;
esac
done
shift $((OPTIND -1))
if [[ $1 ]]; then
endpoint=$1
else
echo "Please specify the endpoint."
usage
exit 1
fi
healthcheck() {
declare url=$1
result=$(curl -I $url 2>/dev/null | grep HTTP/1.1)
echo $result
}
while [[ true ]]; do
result=`healthcheck $endpoint`
declare status
if [[ -z $result ]]; then
status="N/A"
else
status=${result:9:3}
fi
timestamp=$(date "+%Y%m%d-%H%M%S")
if [[ -z $hasUrl ]]; then
echo "$timestamp | $status "
else
echo "$timestamp | $status | $endpoint "
fi
sleep $duration
done