我写了以下代码
var=0
cat $file | while read line do
var=$line
done
echo $var
Run Code Online (Sandbox Code Playgroud)
现在据我所知,管道(|)将导致创建一个子shell,因此第1行的变量var将在最后一行具有相同的值.
然而,这将解决它:
var=0
while read line do
var=$line
done < $file
echo $line
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么重定向不会导致子shell被创建,或者如果你喜欢为什么管道会导致创建一个子shell?
谢谢
所以这是我遇到的一个奇怪的问题; 我有一个脚本试图构建一组命令来运行eval
,这些脚本需要作为一堆其他命令的一部分在子shell中运行(所以我可以异步运行它们).这些命令包括用于保护内部空间等值的引用,但是它们被视为引文根本不存在.
例如:
cmd="echo 'Foo Bar'"
$(eval "$cmd" | sort) &
Run Code Online (Sandbox Code Playgroud)
结果出现"Foo:command not found"的错误
虽然运行它更直接工作得很好 - 所以:
eval "$cmd" | sort
Run Code Online (Sandbox Code Playgroud)
我意识到这个例子不是很有趣,但我不明白的是为什么报价丢失以及如何避免它,同时仍然在适当的子shell中执行(在后台处理和不处理).
我想知道为什么我没有得到相同的输出:
ls -1 -tF | head -n 1
和
echo $(ls -1 -tF | head -n 1)
我试图获取最后修改过的文件,但是在子shell中使用它有时会得到多个文件?
为什么那样以及如何避免?
运行此脚本时:
#!/bin/sh -ex
if [[ $# -ne 1 ]]; then
echo "./import-public-ssh-key.sh <absolute path to public key>"
exit 1;
fi
PATH=$1
KEY=$(basename ${PATH})
Run Code Online (Sandbox Code Playgroud)
我得到:
./import-public-ssh-key.sh: line 9: basename: command not found
Run Code Online (Sandbox Code Playgroud)
没有子shell的basename
作品:
$ basename /Users/mles/.ssh/id_rsa.pub
id_rsa.pub
Run Code Online (Sandbox Code Playgroud)
为什么basename
不在子shell中工作?如果这是相关的,我在 mac 上。
当我尝试这样的事情时:
( echo && { echo ; echo } )
Run Code Online (Sandbox Code Playgroud)
我越来越:
-bash: syntax error near unexpected token `)'
Run Code Online (Sandbox Code Playgroud)
我确定我需要使用子shell。而且我确定我需要在其中进行分组。那么如何避免语法错误呢?先感谢您!
我尝试通过ssh发送命令,如下所示:
ssh user@192.168.1.1 "echo $(uname -a)"
Run Code Online (Sandbox Code Playgroud)
但是我的问题是,该$(uname -a)
部分实际上创建了一个子外壳,并且不在192.168.1.1服务器上执行,而是在从中执行此命令的系统上执行。
我该如何解决?
PS我的实际示例涉及docker stop all命令,看起来像
docker stop $(docker ps -q)
Run Code Online (Sandbox Code Playgroud)
但我简化了问题。
更新:对不起,我简化了我的问题。我的命令使用Here Document(因为命令内部很复杂,并且使用了许多不同的引号)
ssh user@192.168.1.1 <<SSHCOMMAND
echo $(uname -a)
SSHCOMMAND
Run Code Online (Sandbox Code Playgroud)
因此,Ignacio Vazquez-Abrams解决方案将不起作用
此命令按预期工作:
(dpkg -l | egrep "linux.+3.8.0.*44" | awk '{print $2}')
linux-generic-lts-raring
linux-headers-3.8.0-44
linux-headers-3.8.0-44-generic
linux-headers-generic-lts-raring
linux-image-3.8.0-44-generic
linux-image-generic-lts-raring
Run Code Online (Sandbox Code Playgroud)
但是,当我用bash -c
它运行时不起作用:
bash -c "(dpkg -l | egrep "linux.+3.8.0.*44" | awk '{print $2}')"
ii linux-generic-lts-raring 3.8.0.44.44 Generic Linux kernel image and headers
ii linux-headers-3.8.0-44 3.8.0-44.66~precise1 Header files related to Linux kernel version 3.8.0
ii linux-headers-3.8.0-44-generic 3.8.0-44.66~precise1 Linux kernel headers for version 3.8.0 on 64 bit x86 SMP
ii linux-headers-generic-lts-raring 3.8.0.44.44 Generic Linux kernel headers
ii linux-image-3.8.0-44-generic 3.8.0-44.66~precise1 Linux kernel image for version …
Run Code Online (Sandbox Code Playgroud) 我有一个bash提示符,包含我的主机名使用\h
变量(解释PS1
)或$(uname -n)
.无论我使用哪一个似乎没有什么区别.
对于软件许可证的原因,有时我不得不改变我的主机名,这是通过调用脚本,更新文件来完成/etc/hosts
和/etc/hostname
,并呼吁$ hostname NEWNAME
良好的措施.
当脚本更新我的主机名时,我希望调用脚本的shell有PS1
提示反映更改 - 显示新的主机名.我知道这样做的唯一方法是通过资源我的.bashrc
定义PS1
.但是. "${HOME}/.bashrc"
根据我的理解,在脚本中调用只会修改脚本的环境而不是调用者的环境.
那么如何才能PS1
更新调用者的提示符以自动显示新的主机名?
我在循环中在后台启动1000个子shell.我假设他们使用大致相同的内存量.
for i in `seq 1000`; do
(
echo $i;
sleep 100;
)&
done;
Run Code Online (Sandbox Code Playgroud)
但是,他们没有.每个新的子shell比前一个子shell占用更多的内存.他们的内存使用量正在增加
$ ps -eo size,command --sort -size | grep subshell | head -n2
624 /bin/bash /tmp/subshells.sh
624 /bin/bash /tmp/subshells.sh
$ ps -eo size,command --sort -size | grep subshell | tail -n2
340 /bin/bash /tmp/subshells.sh
340 /bin/bash /tmp/subshells.sh
Run Code Online (Sandbox Code Playgroud)
最小的子shell使用340KB,而最大的子shell需要624KB.
这里发生了什么?有办法避免这种情况吗?我很难过,因为我的并行计算的组织方式需要成千上万个背景的子壳,而且我的内存耗尽.
文件夹结构是这样的:
folder_01
??? folder_02???Dockerfile_02
??? folder_03???Dockerfile_03 & example.sh
Run Code Online (Sandbox Code Playgroud)
在 example.sh 脚本中,我想使用dockerfile_02cd
导航回folder_02
并使用 dockerfile_02 来构建图像,然后导航回当前目录(即folder_03
)这是我尝试过的:
cd ..
cd ./folder_02
docker build . -t image_name
cd ..
cd ./folder_03
Run Code Online (Sandbox Code Playgroud)
在intelliJ中,它给了我警告using a subshell to avoid having to cd back
,我阅读了一些关于它的文档但没有解决方案,有人可以帮助我吗?