Bash

對於 select 命令,腳本文件中的 TMOUT 行為異常。如何解決?

  • September 5, 2020

更新- 看起來這是 bash 4.3.42 的特殊之處,因為它適用於 4.3.46。為那些將來遇到同樣問題的人留下這篇文章。

當我在 bash 命令行中執行此命令時,它可以正常工作:

% (TMOUT=3; s="no selection"; select s in a b c ; do break ; done; echo $s)
1) a
2) b
3) c
#?
no selection
% _

結果:不顯示任何選擇並返回命令行。

但是,當我將它放置一個腳本並執行它時,它會反復請求選擇。

% cat a.sh
#!/bin/bash
(TMOUT=3; s="no selection"; select s in a b c ; do break ; done; echo $s)

% ./a.sh

結果:

1) a
2) b
3) c
#? 1) a
2) b
3) c
#? 1) a
2) b
3) c
#? ^C
% _

為什麼會這樣?我的主要問題是 -如何讓它在腳本中工作?!

更新

% bash --version
GNU bash, version 4.3.42(1)-release (x86_64-unknown-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.

% uname
Linux lx1 2.6.32-642.6.2.el6.x86_64 #1 SMP Mon Oct 24 10:22:33 EDT 2016 x86_64 x86_64 x86_64 GNU/Linux

從手冊:

TMOUT 如果設置為大於零的值,則 TMOUT 被視為內置讀取的預設超時。當輸入來自終端時,如果在 TMOUT 秒後輸入未到達,則選擇命令終止。在互動式 shell 中,該值被解釋為發出主提示後等待輸入的秒數。如果輸入未到達,Bash 在等待該秒數後終止。

所以第一種情況是由於互動式外殼。

$ ps -aef|grep bash; echo "before"; (TMOUT=3; s="no selection"; ps -aef|grep bash; select s in a b c ; do break ; done; echo $s;ps -aef|grep bash);echo "after";ps -aef|grep bash
asktyagi    4926 23767  0 09:40 pts/0    00:00:00 grep --color=auto bash
asktyagi   23767 23741  0 09:03 pts/0    00:00:00 -bash
**before**
asktyagi    4927 23767  0 09:40 pts/0    00:00:00 -bash
asktyagi    4929  4927  0 09:40 pts/0    00:00:00 grep --color=auto bash
asktyagi   23767 23741  0 09:03 pts/0    00:00:00 -bash
1) a
2) b
3) c
#?
no selection
asktyagi    4927 23767  0 09:40 pts/0    00:00:00 -bash
asktyagi    4931  4927  0 09:40 pts/0    00:00:00 grep --color=auto bash
asktyagi   23767 23741  0 09:03 pts/0    00:00:00 -bash
**after**
asktyagi    4933 23767  0 09:40 pts/0    00:00:00 grep --color=auto bash
asktyagi   23767 23741  0 09:03 pts/0    00:00:00 -bash

現在有腳本

$ cat a.sh
#!/bin/bash
(TMOUT=3; s="no selection"; select s in a b c ; do break ; done; echo $s)
ps -aef|grep bash

$ sh a.sh
1) a
2) b
3) c
#?
no selection
asktyagi    5201  5188  0 09:41 pts/0    00:00:00 grep bash
asktyagi   23767 23741  0 09:03 pts/0    00:00:00 -bash

使用timeout命令。這個例子可以改進,但它說明了這一點。首先使用 bash-builtintrap命令在退出時執行一些東西,然後執行你的循環。它執行如下:

#] timeout 3s sh -c 'trap "echo no selection" EXIT; select s in a b c ; do break ; done; '
1) a
2) b
3) c
#? <waits 3 seconds>no selection

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