2016-06-21 22 views
0

我正在編寫一個安裝和配置用戶zsh和zprezto的腳本。爲了我的需要,我寫了一些應該以用戶X(帶有su)和zsh shell來執行多個命令的代碼。奇怪的b​​ash行爲(pipe,su,zsh) - 註釋和用戶中的錯誤沒有改變

行爲不是我所期望的,所以我需要對此代碼進行一些解釋。

su admin -c zsh << EOF 
echo '$USER'; 
echo '$SHELL'; 
EOF 

此代碼僅用於測試:我需要確保命令以admin用戶身份執行並在zsh shell中執行。然而,輸出是:

root 
/bin/zsh 

我只是不明白:在執行命令之前不應該改變用戶嗎?

我試着寫我的代碼,即使有這樣的問題,我得到了另一個奇怪的現象:

cat << EOF | su "admin" -c zsh 

local file="${ZDOTDIR:-$HOME}/.zpreztorc" 
echo "File for $USER : ${ZDOTDIR:-$HOME}/.zpreztorc" 

setopt clobber; # Do not warn when overwritting file 
modules=$(cat "$file" | grep -Pzo "(?s)(zstyle ':prezto:load' pmodule\N*.)([\s\t]*'[a-z]*'[\s\t]*\\\\.)*[\s\t]*'[a-z]*'"); 
firstLineNumber=$(cat "$file" | grep -Fn "$(echo -n "$modules" | head -n 1)" | sed 's/^\([0-9]\+\):.*$/\1/'); 
lastLineNumber=$(cat "$file" | grep -Fn $(echo -n "$modules" | tail -n 1) | sed 's/^\([0-9]\+\):.*$/\1/'); 

for module in ${prezto_modules[@]}; do 
    modules="$modules \\ 
    '$module'"; 
done 

fileContent=$(cat "$file" | sed "$firstLineNumber,$lastLineNumber d"); 

echo -n "$fileContent" | head -n "$((firstLineNumber-1))" > "$file"; 
echo "$modules" >> "$file"; 
echo -n "$fileContent" | tail -n "+$((firstLineNumber))" >> $file; 

cat "$file"; 
EOF 

然而,輸出爲怪太:

cat: '': No such file or directory 
cat: '': No such file or directory 
cat: '': No such file or directory 
grep: loaded: No such file or directory 
grep: loaded: No such file or directory 
grep: loaded: No such file or directory 
grep: loaded: No such file or directory 
grep: loaded: No such file or directory 
grep: loaded: No such file or directory 
grep: loaded: No such file or directory 
grep: autoloaded: No such file or directory 
grep: autoloaded: No such file or directory 
grep: autoloaded: No such file or directory 
grep: autoloaded: No such file or directory 
grep: autoloaded: No such file or directory 
grep: autoloaded: No such file or directory 
cat: '': No such file or directory 
sed: -e expression n°1, caractère 1: commande inconnue: `,' 
tail: incorrect line number: « + » 
File for root : /root/.zpreztorc 

我試着翻譯從法語,不要錯誤我不知道sed的確切傳導,所以我只是讓它保持原樣。 但錯誤本身並不奇怪,看看我的第一個回波線:

echo「File for $ USER:$ {ZDOTDIR: - $ HOME} /。zpreztorc」 - >「根文件:/ root/.zpreztorc「 除了我們是root的事實,它顯示爲最後一行輸出。這意味着在執行代碼之前發現了錯誤,對吧?更奇怪的

的東西:如果我們註釋代碼,錯誤仍然注意到:

su "admin" -c zsh << EOF 
# modules=$(cat "$file" | grep -Pzo "(?s)(zstyle ':prezto:load' pmodule\N*.)([\s\t]*'[a-z]*'[\s\t]*\\\\.)*[\s\t]*'[a-z]*'"); 
EOF 

輸出是:

cat: '': No such file or directory 

你怎麼解釋呢? 感謝

回答

2

這裏有文件<< MARKER將被解釋爲雙引號中的字符串,而<< 'MARKER'將被解釋爲單引號的字符串:當使用<< MARKER之前擴大發送作爲標準輸入

su admin -c zsh << 'EOF' 
    echo "$USER" "this is admin" 
EOF 

su admin -c zsh << EOF 
    echo "$USER" "this is the current user single quotes doesn't prevent it" 
    echo '$USER' 'This is still expanded before send as stdin to zsh' 
EOF 

有關更多信息,請參閱man bash | grep --max-count=1 '<<' -A 11

  <<[-]word 
        here-document 
      delimiter 

    No parameter and variable expansion, command substitution, arithmetic 
    expansion, or pathname expansion is performed on word. If any charac‐ 
    ters in word are quoted, the delimiter is the result of quote removal 
    on word, and the lines in the here-document are not expanded. If word 
    is unquoted, all lines of the here-document are subjected to parameter 
    expansion, command substitution, and arithmetic expansion, the charac‐ 
    ter sequence \<newline> is ignored, and \ must be used to quote the 
    characters \, $, and `. 
+0

謝謝,這正是我需要的! 但是,爲什麼: su admin -c zsh <<'EOF' echo「$ SHELL」; EOF has output: /bin/bash – Wargtek

+0

@Wargtek由於'su'在'-c'運行'zsh'命令時啓動'/ bin/bash'用戶shell,所以如果輸入: ''zsh -c'用$/bin/bash'作爲shell的用戶echo $ SHELL''。 – andlrc