シェル芸160本ノック解答例 その16
技術評論社から出版された『1日1問、半年以内に習得 シェル・ワンライナー160本ノック』の解答例です。
- 解答例の範囲: 問題151〜問題160
- 前回の解答例: シェル芸160本ノック解答例 その15
問題151
$ curl -s https://file.ueda.tech/eki/p/13.xml | grep -B1 山手線 | grep -Po '\d+' | xargs -I@ curl -s https://file.ueda.tech/eki/l/@.xml | grep -A2 station_name | sed 's/^[^<]*//;s/<[^>]*>//g' | xargs -n3 | awk '{printf "printf \047%s \047; curl -s \047https://cyberjapandata2.gsi.go.jp/general/dem/scripts/getelevation.php?lon=%s&lat=%s&outtype=JSON\047 \174 jq .elevation; sleep 1;\n",$1,$2,$3}' | sh | sort -k2,2n
有楽町 2.8
高輪ゲートウェイ 3.1
品川 3.1
御徒町 3.3
田町 3.4
新橋 3.6
東京 3.6
秋葉原 3.8
大崎 3.8
五反田 3.9
浜松町 4.3
神田 4.6
田端 6
日暮里 6.3
鶯谷 8.9
上野 11.3
西日暮里 12.4
渋谷 15.5
駒込 16.6
大塚 19.1
恵比寿 20.4
巣鴨 21.9
高田馬場 22.3
目白 25
原宿 28.4
目黒 29.7
池袋 32.5
代々木 34.9
新大久保 35
新宿 37.5
問題152
あらかじめpython3 -m http.server 8080
で即席Webサーバを立てておきます。
# 即席Webサーバを止めると`Warning`が出力される
$ while :; do sleep 5; curl -sI http://localhost:8080/ |& head -n1 | grep -q ' 200 ' && echo Success || echo Warning; done
Success
Warning
Success
(...略...)
問題153
$ (printf 'HEAD / HTTP/1.1\nHost: www.google.co.jp\n\n'; sleep 1) | telnet www.google.co.jp 80
Trying 2404:6800:400a:813::2003...
Connected to www.google.co.jp.
Escape character is '^]'.
HTTP/1.1 200 OK
Content-Type: text/html; charset=Shift_JIS
(...略...)
Set-Cookie: NID=511=NwUbb2VszSbFHk-HIyo7-jVmMK_3O0TUTDsCW2vTbcyNLpBNoljmUQyofVK5ZSuzLmTeSYwuiu7mFOs5hr07SjTdDU0crEhcCeu1Id0Q1SvgATqg1GI50kGHjVkXieaq47TS1AE7JlC2XBdV3LB6XqiS1VLHgVMo7MthAPrgOKg; expires=Fri, 16-Jun-2023 07:00:56 GMT; path=/; domain=.google.co.jp; HttpOnly
Connection closed by foreign host.
HTTPSの場合は、telnet
の代わりにopenssl s_client
を使います。
$ (printf 'HEAD / HTTP/1.1\nHost: www.google.co.jp\n\n'; sleep 1) | openssl s_client -connect www.google.co.jp:443 -quiet -no_ign_eof
depth=2 C = US, O = Google Trust Services LLC, CN = GTS Root R1
verify return:1
depth=1 C = US, O = Google Trust Services LLC, CN = GTS CA 1C3
verify return:1
depth=0 CN = *.google.co.jp
verify return:1
HTTP/1.1 200 OK
Content-Type: text/html; charset=Shift_JIS
(...略...)
Set-Cookie: NID=511=kjAu-js059PGQsuT-5il998QG2g-vtMXFOXMKDbHHC4v3cLm1gC0ueX7iMQDUIvhZF13LY0_R_W1PFRIr4MzA1OqquLIFWPJPd9rRVTQXhgHtQ8SVaj2fk6bGaJZIeRFkB8PVkv4BgGxCYnrgta3a4KLFYF81NKg0c83YlOibkY; expires=Fri, 16-Jun-2023 07:57:50 GMT; path=/; domain=.google.co.jp; HttpOnly
Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
DONE
問題154
$ for c in {curl,'wget -qO-',dig,nslookup,'ping -c1'}; do (sudo strace -f $c www.example.com >/dev/null) |& grep -q '/etc/hosts' && (echo $c | sed 's/ .*//'); done
curl
wget
ping
問題155
$ while :; do printf 'HTTP/1.1 200 OK\nContent-Length: 4\n\ntest' | nc -l -p 8080; [ $? -ne 0 ] && break; done
GET / HTTP/1.1
Host: localhost:8080
User-Agent: curl/7.74.0
Accept: */*
別の端末からcurl
して、レスポンスが受け取れるか確認をします。
$ curl http://localhost:8080
test
不正なContent-Length
で実行する場合、curl
が正常終了できるようnc
に-q <秒数>
オプションを付ける必要があります。
$ while :; do printf 'HTTP/1.1 200 OK\nContent-Length: 5\n\ntest' | nc -q 1 -l -p 8080; [ $? -ne 0 ] && break; done
GET / HTTP/1.1
Host: localhost:8080
User-Agent: curl/7.74.0
Accept: */*
再度、別の端末からcurl
して、レスポンスが受け取れるか確認をします。
$ curl http://localhost:8080
curl: (18) transfer closed with 1 bytes remaining to read
test
「1バイト読み残して転送を終了」という警告が出ています。
問題156
$ for d in $(cat domains.txt); do printf "$d "; dig $d | sed '/^;; ANSWER/,/^;; Query/!d' | grep -P '(\d{1,3}\.){3}\d{1,3}$' | wc -l; done | awk '$2>1{print $1}'
gihyo.jp
なお、表示されているFQDNは、2022年12月21日現在のものです。
問題157
問題157小問1
$ sudo tcpdump -nx -c 1 icmp 2>/dev/null
13:31:08.233401 IP 192.168.1.10 > 104.22.59.251: ICMP echo request, id 54703, seq 1, length 64
0x0000: 4500 0054 f73e 4000 4001 dda6 c0a8 010a
0x0010: 6816 3bfb 0800 7c7b d5af 0001 8cdd a363
0x0020: 878f 0300 0809 0a0b 0c0d 0e0f 1011 1213
0x0030: 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223
0x0040: 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233
0x0050: 3435 3637
なお、表示されているping
の送信内容は一例です。
問題157小問2
$ sudo tcpdump -nx -c 1 icmp 2>/dev/null | awk '$1~/^0x/{$1="";printf $0}' | sed -E 's/.* 0800( [0-9a-f]{4}){2} 0001 (.*)/\2\n/'
ddeb a363 39c0 0a00 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637
なお、表示されているICMPエコー要求メッセージのデータフィールドは一例です。
問題158
問題158小問1
$ ping -4 gihyo.jp | (grep -Po -m1 'ttl=\d+' && pkill -u $USER ping) | sed 's/.*=//'
57
なお、表示されているTTLの値は一例です。
問題158小問2
$ sudo traceroute -4 -I gihyo.jp 2>/dev/null | tail -n1 | awk '{print $1-1}'
7
なお、経由ノード数はネットワーク環境により異なります。
問題159
$ time cat sites.txt | xargs -L1 -P0 host -tA -R0 -W0 -4 | awk '/not found:/{print $2}' > fake_sites.txt
real 0m0.966s
user 0m0.548s
sys 0m0.338s
# 存在しないドメインを確認
$ cat fake_sites.txt
taobao.come
rarirure.ro
yandex.runrun
問題160
$ openssl s_client -connect example.com:443 </dev/null 2>/dev/null | openssl x509 -noout -dates
notBefore=Mar 14 00:00:00 2022 GMT
notAfter=Mar 14 23:59:59 2023 GMT
なお、表示されているサーバ証明書の有効期間は、2022年12月24日現在のものです。
完走した感想
160問すべてを完走した感想ですが、日付や時刻の取り扱いや疑似ファイルシステムの利用、そしてgit
のサブコマンド群の使い方など、今まである程度シェル芸に触れてきたにもかかわらず決して明るいとは言えない分野の知識が得られて良かったです。また、本来文字列の操作が中心であるシェル上でバイナリデータを取り扱うのも意外性があって楽しめました。
シェル芸というものは、PCではなく自分の脳にインストールするタイプのソフトウェアのような何かであるのかもしれません(そしてアンインストールする方法/必要はおそらく、ない)。
それでは、最後に。執筆陣のみなさん、どうもありがとうございました。