bash - run - ssh script password




將命令作為輸入傳遞給另一個命令(su,ssh,sh等) (2)

shell腳本是一系列命令。 shell將讀取腳本文件,並依次執行這些命令。

在通常的情況下,這裡沒有驚喜; 但是一個常見的初學者錯誤是假設 某些 命令將從shell接管,並開始在腳本文件中執行以下命令,而不是當前運行此腳本的shell。 但這不是它的工作原理。

基本上,腳本的工作方式與交互式命令 完全相同 ,但需要正確理解它們的工作原理。 交互式地,shell讀取命令(來自標準輸入),運行該命令(使用來自標準輸入的輸入),並且當它完成時,它讀取另一個命令(來自標準輸入)。

現在,在執行腳本時, 標準輸入仍然是終端 (除非您使用了重定向),但命令是從腳本文件中讀取的,而不是從標準輸入中讀取的。 (相反的情況確實非常麻煩 - 任何 read 都會佔用腳本的下一行, cat 會淹沒腳本的所有其餘內容,並且無法與它進行交互!)腳本文件 包含命令執行它的shell實例(儘管你當然可以使用here文檔等將輸入嵌入為命令參數)。

換句話說,這些“誤解”的命令( susshshsudobash 等)在單獨運行時(沒有參數)將啟動交互式shell,並且在交互式會話中,這顯然很好; 但是從腳本運行時,通常不是你想要的。

所有這些命令都有通過除交互式終端會話之外的方式接受命令的方法。 通常,每個命令都支持將命令作為選項或參數傳遞的方法:

su root -c 'who am i'
ssh [email protected] uname -a
sh -c 'who am i; echo success'

其中許多命令也會接受標準輸入的命令:

printf 'uname -a; who am i; uptime' | su
printf 'uname -a; who am i; uptime' | ssh [email protected]
printf 'uname -a; who am i; uptime' | sh

這也方便你在這裡使用文件:

ssh [email protected] <<'____HERE'
    uname -a
    who am i
    uptime
____HERE

sh <<'____HERE'
    uname -a
    who am i
    uptime
____HERE

對於接受單個命令參數的命令,該命令可以是 shbash 具有多個命令:

sudo sh -c 'uname -a; who am i; uptime'

順便說一句,您通常不需要顯式 exit 因為該命令將在執行您傳入執行的腳本(命令序列)時終止。

我有一個腳本,我需要啟動一個命令,然後將一些額外的命令 作為命令 傳遞給該命令。 我試過了

su
echo I should be root now:
who am I
exit
echo done.

...但它不起作用: su 成功,但命令提示符只是盯著我。 如果我在提示符下鍵入 exit ,那麼 echowho am i 等開始執行! echo done. 根本沒有執行。

同樣,我需要這個在 ssh 上工作:

ssh remotehost
# this should run under my account on remotehost
su
## this should run as root on remotehost
whoami
exit
## back
exit
# back

我該如何解決這個問題?

我正在尋找能夠以一般方式解決這個問題的答案,而這些答案並不特別針對 sussh 。 目的是使這個問題成為這種特定模式的 canonical


添加到 的 answer :

重要的是要記住,格式化為另一個shell的here-document的腳本部分在具有自己的環境的不同shell中執行(甚至可能在不同的機器上)。

如果腳本的那個塊包含參數擴展,命令替換和/或算術擴展,那麼必須使用shell的here-document工具略有不同,具體取決於您希望執行這些擴展的位置。

1.所有擴展必須在父shell的範圍內執行。

那麼這裡的文件的分隔符必須是不加 引號的

command <<DELIMITER
...
DELIMITER

例:

#!/bin/bash

a=0
mylogin=$(whoami)
sudo sh <<END
    a=1
    mylogin=$(whoami)
    echo a=$a
    echo mylogin=$mylogin
END
echo a=$a
echo mylogin=$mylogin

輸出:

a=0
mylogin=leon
a=0
mylogin=leon

2.所有擴展必須在子shell的範圍內執行。

然後必須 引用 此處文檔的分隔符。

command <<'DELIMITER'
...
DELIMITER

例:

#!/bin/bash

a=0
mylogin=$(whoami)
sudo sh <<'END'
    a=1
    mylogin=$(whoami)
    echo a=$a
    echo mylogin=$mylogin
END
echo a=$a
echo mylogin=$mylogin

輸出:

a=1
mylogin=root
a=0
mylogin=leon

3.必須在子shell中執行一些擴展,有些擴展在父級中。

然後,必須取消 引用 此文檔的分隔符,並且必須 轉義必須在子shell中執行的那些擴展表達式

例:

#!/bin/bash

a=0
mylogin=$(whoami)
sudo sh <<END
    a=1
    mylogin=\$(whoami)
    echo a=$a
    echo mylogin=\$mylogin
END
echo a=$a
echo mylogin=$mylogin

輸出:

a=0
mylogin=root
a=0
mylogin=leon




sh