腳本:
#!/bin/sh
#
# reads stdin/file and copies it to clipboard
# clears it after 30s
#
cat "${1:-/dev/stdin}" | timeout 30 xclip -i -selection clipboard -r -verbose &>/dev/null &
我可以看到只有 stdin 不起作用(使用 bash 它可以在 stdin/file 上工作)。
PS verbose 用於使 xclip 不成為守護程式。
答案1
&>
是一個 bashism,你必須將其更改>/dev/null 2>&1
為 POSIX shell
答案2
[這個答案是關於腳本中的非同步管道;對於已棄用的&>
bash 運算子以及為什麼您應該始終使用>output 2>&1
它,請參閱過時和不建議使用的語法]
#! /bin/sh cat "${1:-/dev/stdin}" | ... &
這裡有一個非同步運行的管道(因為由 終止&
),從腳本啟動,即從禁用作業控制的 shell 啟動。
根據標準:
command1 & [command2 & ... ]
在執行任何明確重定向之前,非同步清單的標準輸入應被視為分配給具有與
/dev/null
.
問題是dash
、ksh
、mksh
、yash
等將「非同步清單」解釋為任何命令,包括管道,並將重定向第一個命令的標準輸入/dev/null
:
$ echo foo | dash -c 'cat | tr fo FO & echo DONE'
DONE
$ echo | dash -c 'readlink /proc/self/fd/0 | cat & echo DONE'
DONE
/dev/null
但bash
只會將其解釋為“簡單命令”,並且只會在/dev/null
其執行時重定向其標準輸入不是管道的一部分:
$ echo foo | bash -c 'cat | tr fo FO & echo DONE'
DONE
FOO
$ echo | bash -c 'readlink /proc/self/fd/0 | cat & echo DONE'
DONE
pipe:[69872]
$ echo | bash -c 'readlink /proc/self/fd/0 & echo DONE'
DONE
/dev/null
$ bash -c 'cat | tr a A & echo DONE'
DONE
cat: -: Input/output error
zsh
/dev/null
只有當原始標準輸入是 tty 時才重定向它,而不是當它是其他類型的檔案時:
$ zsh -c 'readlink /proc/self/fd/0 &' </dev/tty
/dev/null
$ zsh -c 'readlink /proc/self/fd/0 &' </dev/zero
/dev/zero
在所有 shell 中都有效的解決方法是將標準輸入複製到另一個檔案描述符中,並從中重定向第一個命令的標準輸入:
#! /bin/sh
exec 3<"${1:-/dev/stdin}"
cat <&3 | timeout 30 xclip -i -selection clipboard -verbose -r >/dev/null 2>&1 &