各種shell的fd數量是否固定?
比方說:
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 是否總是包含腳本的路徑?