Bash

各種shell的fd數量是否固定?

  • September 26, 2020

比方說:

xb@dnxb:/tmp$ echo 'ls -l /proc/$$/fd | grep a.sh' > a.sh; \
> while IFS='' read -r f; do \
> echo "$f"; "$f" a.sh; \
> done < <(tail -n +2 /etc/shells)
/bin/sh
lr-x------ 1 xiaobai xiaobai 64 Jan  20 00:09 10 -> /tmp/a.sh
/bin/dash
lr-x------ 1 xiaobai xiaobai 64 Jan  20 00:09 10 -> /tmp/a.sh
/bin/bash
lr-x------ 1 xiaobai xiaobai 64 Jan  20 00:09 255 -> /tmp/a.sh
/bin/rbash
lr-x------ 1 xiaobai xiaobai 64 Jan  20 00:09 255 -> /tmp/a.sh
/bin/zsh
lr-x------ 1 xiaobai xiaobai 64 Jan  20 00:09 11 -> /tmp/a.sh
/usr/bin/zsh
lr-x------ 1 xiaobai xiaobai 64 Jan  20 00:09 11 -> /tmp/a.sh
/bin/ksh93
lr-x------ 1 xiaobai xiaobai 64 Jan  20 00:09 10 -> /tmp/a.sh
/bin/rksh93
lr-x------ 1 xiaobai xiaobai 64 Jan  20 00:09 10 -> /tmp/a.sh
xb@dnxb:/tmp$ 

bash 是否始終具有固定的 fd 編號 255 而 zsh 預設具有固定的 fd 編號 11?

我問這個問題是因為我需要提取從任何 shell 程序執行的完整路徑。我想知道我是否可以硬編碼我的腳本來引用這個固定數字。

請注意,這是針對個人腳本,並不意味著要在關鍵業務上執行,所以我不是在尋找 100% 可靠的,但fd 號碼在大多數情況下是否固定

$$ UPDATE $$:

我不解析的cmdline原因是:

xb@dnxb:~/Downloads$ cat foo.sh 
#!/bin/bash
cat "/proc/$$/cmdline" | tr '\0' '\n'
readlink -f /proc/$$/fd/255

xb@dnxb:~/Downloads$ bash --norc foo.sh --norc
bash
--norc
foo.sh
--norc
/home/xiaobai/Downloads/foo.sh
xb@dnxb:~/Downloads$ 

如您所見,只能fd給出完整路徑/home/xiaobai/Downloads/foo.sh,但不能給出cmdline. 並且腳本無法區分foo.sh或者--norc是路徑或選項,因為foo.sh可以出現在任何選項位置,除非我進行醜陋的檢查,例如它不是 startswith --

雖然fd即使我這樣做也沒有問題產生正確的完整路徑bash --norc foo.sh --norc foo2.sh

無論如何,我剛剛意識到我的任務不必檢查這個,因為我注意到除了自定義程序之外沒有系統程序是從 shell 繼承的。但仍然任何答案都會對未來的讀者有所幫助。

您唯一可以確定的是它不會是 fds 1 到 9,因為這些是保留給使用者在 POSIX sh 實現中使用的,並且在這種sh < your-script情況下可以使用 0。yash 將其擴展到 fds 1 到 99。

您不能依賴它是一個固定值,因為如果 fd 在啟動時已經打開,shell 將使用不同的值。大多數 shell 似乎使用 9 以上的第一個空閒 fds(或 99 用於 yash)作為它們的內部 fds。bash似乎正在使用 255 並且在無法使用時下降而不是上升:

bash-5.0$ bash a 255> /dev/null
total 0
lrwx------ 1 chazelas chazelas 64 Sep 26 18:03 0 -> /dev/pts/12
lrwx------ 1 chazelas chazelas 64 Sep 26 18:03 1 -> /dev/pts/12
lrwx------ 1 chazelas chazelas 64 Sep 26 18:03 2 -> /dev/pts/12
lr-x------ 1 chazelas chazelas 64 Sep 26 18:03 254 -> /home/chazelas/a
l-wx------ 1 chazelas chazelas 64 Sep 26 18:03 255 -> /dev/null
bash-5.0$ ulimit -n 123
bash-5.0$ bash a
total 0
lrwx------ 1 chazelas chazelas 64 Sep 26 18:03 0 -> /dev/pts/12
lrwx------ 1 chazelas chazelas 64 Sep 26 18:03 1 -> /dev/pts/12
lr-x------ 1 chazelas chazelas 64 Sep 26 18:03 122 -> /home/chazelas/a
lrwx------ 1 chazelas chazelas 64 Sep 26 18:03 2 -> /dev/pts/12

使用$0獲取正在執行的腳本的路徑通常是最好的方法。另請參閱:$0 是否總是包含腳本的路徑?

引用自:https://unix.stackexchange.com/questions/418263