奇怪的bash行为(pipe,su,zsh) - 注释和用户中的错误没有改变
问题描述:
我正在编写一个安装和配置用户zsh和zprezto的脚本。为了我的需要,我写了一些应该以用户X(带有su)和zsh shell来执行多个命令的代码。奇怪的bash行为(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
你怎么解释呢? 感谢
答
这里有文件<< 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 `.
谢谢,这正是我需要的! 但是,为什么: su admin -c zsh Wargtek
@Wargtek由于'su'在'-c'运行'zsh'命令时启动'/ bin/bash'用户shell,所以如果输入: ''zsh -c'用$/bin/bash'作为shell的用户echo $ SHELL''。 – andlrc