リダイレクトのエラーの謎2
Sun Sep 24 20:38:36 JST 2023 (modified: Sun Sep 24 20:41:05 JST 2023)
views: 517, keywords:シェル芸, 自作シェル, bash この記事は最終更新日が1年以上前のものです。
このときのリダイレクトに関する調査の続きです。
n>&m
のn
が大きいときにm
が怒られるパターン
上記のリンク先の記事では触れてませんが、 もう一つ、Bashにはこういう変な挙動があります。
ulimit -n
$ 1024 #開けるファイル記述子の上限は1024
ls /var 1000>&2 #これは大丈夫
$ backups cache crash lib local lock log mail metrics opt run snap spool tmp
ls 1024>&2
$ bash: 2: 不正なファイル記述子です #なぜか1024ではなく2のほうが叱られる
ls 100000000000000000000>&2
$ ls: '100000000000000000000' にアクセスできません:(略) #数字が大きいとちゃんと叱られる
$ ls 1024>&2
では1024のほうを叱って欲しいのに、なぜか2のほうが叱られます。
で、これなんでだろうと思ってBashのコードを読んでみましたが、 わけわかめで玉砕しました。しかしこのたび、 自分で処理を書いてみたらなんとなく分かりました。 Rustで書くとこんな感じ。
/* m>&n の処理 */
31 match unistd::dup2(n, m) {
32 Ok(_) => true,
33 Err(Errno::EBADF) => {
34 eprintln!("sush: {}: Bad file descriptor", n);
35 false
36 },
37 Err(_) => {
38 eprintln!("sush: dup2 Unknown error");
39 false
40 },
41 }
dup2はerrno
にEBADF
しか残さないので、 31行目のm
とn
のどっちがダメなファイル記述子なのか分かりません。 なので、34行目でn
のほうを断罪するしかないという実装になりました。 dup2を実行する前になにか変だと分かればこれは防げます。 ls 100000000000000000000>&2
の場合は文字列100000....
を数字にするときにエラーになるので、 さっきのBashの例では10000....
のほうが叱られるのだと思われます。
まだわからんこと
前回のこれのやりなおしですが、これがまだ分かりません。情報求む。
echo 1>&1000
$ bash: 1000: 不正なファイル記述子です #開いてないので1000が怒られる
echo 2>&1000
$ bash: 1000: 不正なファイル記述子です #同上
echo 3>&1000
$ bash: 1000: 不正なファイル記述子です #同上
echo 1>&1000000000000
$ bash: 1000000000000: 不正なファイル記述子です #同上
echo 2>&1000000000000
$ bash: 2: 不正なファイル記述子です #???????????????????????
echo 3>&1000000000000
$ bash: 3: 不正なファイル記述子です #これは3が開いてないので分かる