リダイレクトのエラーの謎2
Sun Sep 24 20:38:36 JST 2023 (modified: Sun Sep 24 20:41:05 JST 2023)
views: 1471, keywords:シェル芸, 自作シェル, bash この記事は最終更新日が2年以上前のものです。
このときのリダイレクトに関する調査の続きです。
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が開いてないので分かる
ノート
Tweet