【问题标题】:Strange bash behaviour (pipe, su, zsh) - Errors in comments and user not changed奇怪的 bash 行为(管道、su、zsh) - 评论中的错误和用户未更改
【发布时间】:2016-06-21 20:48:33
【问题描述】:

我正在编写一个脚本来安装和配置用户 zsh 和 zprezto。根据我的需要,我编写了一些代码,应该以用户 X(使用 su)和 zsh shell 的身份执行多个命令。

这种行为不是我所期望的,所以我需要一些关于这段代码的解释。

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

此代码仅用于测试:我需要确保以用户 admin 和 zsh shell 执行命令。但是,输出是:

root
/bin/zsh

我只是不明白:在执行命令之前不应该 su 更改用户吗?

即使遇到这个问题,我也尝试编写代码,但出现了另一个奇怪的行为:

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 "$USER 文件:${ZDOTDIR:-$HOME}/.zpreztorc" --> "root 文件:/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

你怎么解释? 谢谢

【问题讨论】:

    标签: bash pipe zsh eof su


    【解决方案1】:

    此处带有&lt;&lt; MARKER 的文档将被解释为双引号字符串,而&lt;&lt; 'MARKER' 将被解释为单引号字符串:

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

    虽然使用 &lt;&lt; MARKER 在作为标准输入发送之前被扩展

    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 '&lt;&lt;' -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 `.
    

    【讨论】:

    • 谢谢,这正是我需要的!但是,为什么会这样: su admin -c zsh
    • @Wargtek 因为su 启动用户shell,即/bin/bash,而-c 运行命令zsh,如果您键入:zsh -c 'echo $SHELL',用户具有@ 987654333@ 作为外壳。
    猜你喜欢
    • 2021-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-13
    • 1970-01-01
    相关资源
    最近更新 更多