Assign a TTY as STDIN,解決腳本互動問題



前言

  • 有時候寫腳本,會套其他工具或產品;如果這個工具會需要跟使用者互動、指定參數、或輸入密碼等,在腳本執行的時候,通常都會直接跳掉。不外乎是抱怨 non-interactive 或是 tty 問題。
  • 這篇記錄一下一個簡單的寫法。



說明

正常情況、預期情況

例如,我寫了一個腳本,要在覆蓋檔案前,先確認使用者是否確認 (y/n):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#!/bin/bash

echo start

prepare () {
  touch old_file.txt
  touch new_file.txt
}

mv_with_i () {
  mv -i new_file.txt old_file.txt
}

prepare
mv_with_i
echo "done"

執行後,這個案例沒有問題,他會正確詢問,如下:

1
2
start
overwrite old_file.txt? (y/n) 

按下 y 以及 enter 鍵就完成工作了


有些意外情況

BUT …

有時候腳本中用了其他的工具,原本預期該工具會有互動,但是卻沒有出現。

舉例,假設我用一個備份工具 my_backup_tool 來做備份,這個工具執行前會問我是否要備份原始檔案:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#!/bin/bash

echo start

prepare () {
  # do preparing
}

do_backup_cluster_job () {
    my_backup_tool backup
}

prepare
do_backup_cluster_job
echo "done"

執行後直接跑出以下結果,連問都沒問

1
2
3
4
start
backup original folders and resources? (y/n)[]
non-interactive terminal is not supported
done

這是因為這個工具需要 tty,但是腳本執行時,沒有 tty


解決方法

解決方式很簡單,只要把你目前 terminal 的 tty 丟給腳本就好了。

新增 </dev/tty 在你的工具執行的地方,如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#!/bin/bash

echo start

prepare () {
  # do preparing
}

do_backup_cluster_job () {
    my_backup_tool backup  </dev/tty
    #                      ^^^^^^^^^^ 這裡
}

prepare
do_backup_cluster_job
echo "done"

執行後就會順利出現結果

1
2
start
backup original folders and resources? (y/n)
Licensed under CC BY-NC-SA 4.0
最後更新 2024-05-08 10:47

主題 StackJimmy 設計