2016-06-21 30 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