【自習】第66回シェル芸勉強会【シェルのプロセスIDで遊ぼう】
現在、介護老人保険施設に入所している母との面会が毎週土曜日の午後にあるため、今回も配信録画で自習しました。
今回はデータファイルを操作する出題はみられず、Bashの特殊変数$$
でシェルのプロセスIDが得られることを利用した問題や、数字を使わずに解答する問題などトリッキーな出題が多くみられました。
- 名称: jus共催 第66回過去10年で最高と言われた01年を上回る出来栄えで1995年以来の出来のシェル芸勉強会(大嘘)
- 開催日: 2023年9月30日(土)
- アナウンスページ:
- Youtubeライブ配信録画:
- 東京会場: https://www.youtube.com/watch?v=lGGr4c85bXk
- 東京会場(Q6の補足): https://www.youtube.com/watch?v=bV1tMKc1yiU
- 大阪サテライト会場 LT: https://www.youtube.com/watch?v=_bR7cQiwEh4
- リンク集: https://b.ueda.tech/?post=shellgei_66_link
Q1
0123456789
と出力してください。コマンド内で数字を使わないでください。
A1
$ printf '\n\n\n\n\n\n\n\n\n\n' | cat -n | sed 's/ *//;$s/.//' | sort | xargs | sed 's/ //g'
0123456789
Q2
つぎのコマンドについて、?
の部分になにか書いて、file
にls
の吐くエラーを記録してください。?
に入れる文字列は何文字でもいいですが、半角スペースと数字は禁止します。
$ ls 存在しないファイル 3>file 2>?
$ cat file
ls: '存在しないファイル' にアクセスできません: そのようなファイルやディレクトリはありません
A2
$ ls 存在しないファイル 3>file 2>&$(($$/$$+$$/$$+$$/$$))
$ cat file
ls: '存在しないファイル' にアクセスできません: そのようなファイルやディレクトリはありません
Q3
1, 2, 3, 4文字それぞれで終了ステータス1を出す方法を考えてみてください。ファイルを操作するためのコマンドの使用(mv
、rsync
、cp
など)や、なくても終了ステータス1が出るような文字を加えて文字数を水増しする方法は禁止です。また1〜4文字まで、互いになるべく違う方法を考えてみてください。
A3
# 1文字で終了ステータス1を出す:
# `!`は終了ステータスを論理否定する`bash`の予約語
$ !
$ echo $?
1
# 2文字で終了ステータス1を出す:
# 入力のリダイレクトによるカレントディレクトリに存在しないファイル`f`の読み込み
$ <f
bash: f: そのようなファイルやディレクトリはありません
$ echo $?
1
# 3文字で終了ステータス1を出す:
# `hcd`はClassic Mac OSで用いられていたHFSファイルシステム用の`cd`コマンド
$ hcd
hcd: No volume is current; use `hmount' or `hvol'
$ echo $?
1
# 4文字で終了ステータス1を出す:
# 後述のA4で用いているのと同じ方法(`w`はログイン中のユーザーとその人のプロセスに関する情報を表示するコマンド)
$ w>&-
w: write error: 不正なファイル記述子です
$ echo $?
1
Q4
シェルに細工をしてtrue
を実行したあとのecho $?
の出力を非ゼロにしてください。true
はビルトインコマンドでも外部コマンドでもかまいません。
A4
$ /bin/true --version >&-
/bin/true: 書き込みエラー: 不正なファイル記述子です
$ echo $?
1
外部コマンドのtrue
にはバージョン情報を表示する--version
オプションがあることと、bash
のリダイレクトでは>&-
という形式で任意のファイル記述子を閉じられることを利用しています。
Q5
どこかのプロセスにおいて、現状のシステムの設定で作れる最も大きい番号のファイル記述子を作って、/proc/プロセス番号/fd
を使って存在を確認してください。確認までワンライナーでお願いします。できる人はワンライナー中で数字を使わないでください。
A5
# `/tmp`ディレクトリに移動してから実行
$ perl -E 'mkdir "D";for('a'..'zzz'){open $_,">","D/$_" or exit;$n=fileno $_}END{system("ls -l /proc/$$/fd/$n");system("rm -fR D")}'
l-wx------ 1 mitsuhisa mitsuhisa 64 10月 6 01:42 /proc/7382/fd/1023 -> /tmp/D/amg
現状のシステムの設定で作れるファイル記述子の個数はulimit -n
で知ることができ、解答例の/proc/7382/fd/1023
と対応していることがわかります。
# 有効なファイル記述子の値は0から1023までの1024個
$ ulimit -n
1024
Q6
いまのBashのプロセスで、10以上のファイル記述子を使い切ってください。できる人はワンライナー中で数字を使わないでください。
A6
# ワンライナー実行前:
$ ls /proc/$$/fd | sort -n
0
1
2
255
# 解答例のワンライナーを実行:
# ※`n`の値が255(既存の数値)と1024(ファイル記述子の最大値+1)の場合はエラー
$ Z=$(($$/$$+$$/$$)); for n in $(seq $(((Z<<Z)+Z)) $(ulimit -n)); do exec {n}>&$Z; done
bash: リダイレクトエラー: ファイル記述子を複製できません: ファイルを開きすぎです
bash: 2: ファイルを開きすぎです
bash: リダイレクトエラー: ファイル記述子を複製できません: ファイルを開きすぎです
bash: 2: ファイルを開きすぎです
# ワンライナー実行後:
$ ls /proc/$$/fd | sort -n
0
1
2
10
11
12
13
14
15
16
(...略...)
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023