检测 /dev/tty 是否可用和功能的跨平台方法
Cross-platform method to detect whether /dev/tty is available & functional
我有一个 bash 脚本,我想从中访问 /dev/tty,但只有当它可用时才可以。
当它不可用时(在我的例子中:当 运行 我的脚本在 GitHub 操作中)然后当我尝试访问它时我得到 /dev/tty: No such device or address
,我正在尝试提前检测以避免错误并提供回退行为。
为此,我需要一个 bash 测试,它可以清楚地检测到这种情况,并且可以跨平台可靠地工作(即不使用 tty
命令,它有问题 on Mac).
我目前正在使用 [[ -e "/dev/tty" ]]
,但它不起作用 - 即使在 GitHub 操作上,它似乎 return 也是正确的,似乎 /dev/tty 存在,但是访问它会失败。我应该改用什么?
似乎适应this answer from this question on ServerFault(标题为如果shell在交互模式下是运行,我如何检查bash?,这与您的问题很接近,尽管不是完全重复)可能是您用例的解决方案。
那么,你可以试试写:
[ -t 0 ] && [ -t 1 ] && echo your code
- 或
[ -t 0 ] && echo your code
?
为了完整起见,这里有一个 link 记录了这个 POSIX 标志 -t
,因此它是可移植的:
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html
-t file_descriptor
True if file descriptor number file_descriptor is open and is associated with a terminal.
False if file_descriptor is not a valid file descriptor number, or if file descriptor number file_descriptor is not open, or if it is open but is not associated with a terminal.
此外,如果您使用 bash
(不仅仅是 POSIX-compliant shell),您可能希望将这个想法与特殊的 255
文件描述符编号结合起来: [ -t 255 ]
.
来源:Unix&Linux-SE,
That 255
file descriptor is an open handle to the controlling tty and is only used when bash
is run in interactive mode.
[…]
− In Bash, what is file descriptor 255 for, can I use it? (by @mosvy)
试试这个方法:
if test "$(ps -p "$$" -o tty=)" = "?"; then
echo "/dev/tty is not available."
else
echo "/dev/tty is available."
fi
除了此线程中提到的其他答案(以及作为涉及 $-
、), what about this other idea mentioned in the bash manual?
的其他想法的替代方案
if [ -z "$PS1" ]; then
echo This shell is not interactive
else
echo This shell is interactive
fi
在测试了很多有前途但不是很完美的建议(参见其他答案)之后,我想我已经找到了完全符合我需要的解决方案:
if sh -c ": >/dev/tty" >/dev/null 2>/dev/null; then
# /dev/tty is available and usable
else
# /dev/tty is not available
fi
说明:
: >/dev/tty
什么都不做(使用 :
bash 内置)并将什么都输出到 /dev/tty,从而检查它是否存在并且它是可写的,但是实际上没有产生任何可见的输出。如果这成功了,我们就很好了。
如果我们在没有 /dev/tty 的顶层执行此操作,bash 本身会在我们的输出中产生一个嘈杂的错误,抱怨 /dev/tty 不可用。这不能被重定向和静音,因为它来自 bash 本身,而不是 :
命令。
用 sh -c "..." >/dev/null 2>/dev/null
包装它在 bash 子 shell 中运行测试,删除 stdout/stderr,因此在仍然返回整体退出代码的同时消除所有错误和警告。
欢迎提出进一步改进的建议。作为参考,我正在使用 setsid <command>
进行测试,这似乎很好地模拟了我遇到问题的无 TTY 环境。
而不是产生一个新的 shell 进程来测试 /dev/tty
是否可以 真的 可以打开写入(test -w
谎言,你知道?),您可以尝试将 stdout 从 subshell 重定向到 /dev/tty,如下所示:
if (exec < /dev/tty) ; then
# /dev/tty is available
else
# no tty is available
fi
这是 POSIX 语法,应该适用于任何 shell。
我有一个 bash 脚本,我想从中访问 /dev/tty,但只有当它可用时才可以。
当它不可用时(在我的例子中:当 运行 我的脚本在 GitHub 操作中)然后当我尝试访问它时我得到 /dev/tty: No such device or address
,我正在尝试提前检测以避免错误并提供回退行为。
为此,我需要一个 bash 测试,它可以清楚地检测到这种情况,并且可以跨平台可靠地工作(即不使用 tty
命令,它有问题 on Mac).
我目前正在使用 [[ -e "/dev/tty" ]]
,但它不起作用 - 即使在 GitHub 操作上,它似乎 return 也是正确的,似乎 /dev/tty 存在,但是访问它会失败。我应该改用什么?
似乎适应this answer from this question on ServerFault(标题为如果shell在交互模式下是运行,我如何检查bash?,这与您的问题很接近,尽管不是完全重复)可能是您用例的解决方案。
那么,你可以试试写:
[ -t 0 ] && [ -t 1 ] && echo your code
- 或
[ -t 0 ] && echo your code
?
为了完整起见,这里有一个 link 记录了这个 POSIX 标志 -t
,因此它是可移植的:
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html
-t file_descriptor
True if file descriptor number file_descriptor is open and is associated with a terminal.
False if file_descriptor is not a valid file descriptor number, or if file descriptor number file_descriptor is not open, or if it is open but is not associated with a terminal.
此外,如果您使用 bash
(不仅仅是 POSIX-compliant shell),您可能希望将这个想法与特殊的 255
文件描述符编号结合起来: [ -t 255 ]
.
来源:Unix&Linux-SE,
That
255
file descriptor is an open handle to the controlling tty and is only used whenbash
is run in interactive mode. […]− In Bash, what is file descriptor 255 for, can I use it? (by @mosvy)
试试这个方法:
if test "$(ps -p "$$" -o tty=)" = "?"; then
echo "/dev/tty is not available."
else
echo "/dev/tty is available."
fi
除了此线程中提到的其他答案(以及作为涉及 $-
、
if [ -z "$PS1" ]; then
echo This shell is not interactive
else
echo This shell is interactive
fi
在测试了很多有前途但不是很完美的建议(参见其他答案)之后,我想我已经找到了完全符合我需要的解决方案:
if sh -c ": >/dev/tty" >/dev/null 2>/dev/null; then
# /dev/tty is available and usable
else
# /dev/tty is not available
fi
说明:
: >/dev/tty
什么都不做(使用 :
bash 内置)并将什么都输出到 /dev/tty,从而检查它是否存在并且它是可写的,但是实际上没有产生任何可见的输出。如果这成功了,我们就很好了。
如果我们在没有 /dev/tty 的顶层执行此操作,bash 本身会在我们的输出中产生一个嘈杂的错误,抱怨 /dev/tty 不可用。这不能被重定向和静音,因为它来自 bash 本身,而不是 :
命令。
用 sh -c "..." >/dev/null 2>/dev/null
包装它在 bash 子 shell 中运行测试,删除 stdout/stderr,因此在仍然返回整体退出代码的同时消除所有错误和警告。
欢迎提出进一步改进的建议。作为参考,我正在使用 setsid <command>
进行测试,这似乎很好地模拟了我遇到问题的无 TTY 环境。
而不是产生一个新的 shell 进程来测试 /dev/tty
是否可以 真的 可以打开写入(test -w
谎言,你知道?),您可以尝试将 stdout 从 subshell 重定向到 /dev/tty,如下所示:
if (exec < /dev/tty) ; then
# /dev/tty is available
else
# no tty is available
fi
这是 POSIX 语法,应该适用于任何 shell。