这个问题与“当我们在 shell 上输入一个简单的命令时会发生什么?”的问题相关。我之前发过。(我认为分开发布会更好。但如果没有,请告诉我。)
我从上一个问题中了解到,shell 内置命令被特殊处理,正常的外部命令在子进程上执行。
这一次,我想跟踪系统调用,例如 fork、clone 或 execve,以监视键入命令后真正发生的情况。但是execve("bin/ls",,,) = 0当我这样执行时,我只能跟踪一个 execve 调用strace。
strace -etrace=execve,clone ls
Run Code Online (Sandbox Code Playgroud)
这意味着,正如我猜的那样,我只能监视在创建子进程后调用的系统调用。
要监视与创建新进程相关的所有系统调用,我必须做什么? 在这种情况下,使用bash -clike调用命令strace -etrace=execve,clone bash -c '{ ls; }'会有所帮助吗?
我目前正在子 shell 中启动后台进程,想知道如何将其 pid 编号分配给子 shell 范围之外的变量?
我尝试了许多不同的方法,但MYPID始终设置为0.
MYPID = 0;
({ sleep 2 & }; $MYPID=$!)
({ sleep 2 & }; echo $!) > $MYPID
Run Code Online (Sandbox Code Playgroud)
它返回值的唯一方法是:
$MYPID=$({ sleep 2 & }; echo $!)
Run Code Online (Sandbox Code Playgroud)
然而,这会丢弃后台进程指令,它只会在 2 秒后返回结果。
在 zsh 中,以下 2 个命令的结果不同:
a=$(</etc/hosts) && echo $a
echo $(</etc/hosts)
Run Code Online (Sandbox Code Playgroud)
第一个逐行打印内容,而第二个将整个内容打印在一行中。
我猜是因为子shell将结果逐行返回给主echo进程,但我无法确认。
有人可以帮我清除吗?
假设我已经启动了一个完成的控制台应用程序,然后 shell 提示再次出现。但是我怎么能确定它是真正的命令提示符呢?例如,如果应用程序是一个“键盘记录器”,当我尝试退出时它会启动一个假提示怎么办?
那么,我怎样才能检测到我实际上是在一个纯 shell(例如 bash)提示符下呢?
我想在 shell 脚本中调用一个命令以进行持续集成。退出状态 0 表示成功,否则失败。我正在编写一个包装脚本来运行多个命令,如果其中一个发生任何错误,则失败。
但是,其中一个命令(第 3 方软件)在失败时不符合“事实上的”退出状态 != 1。但是,如果出现故障,它会在 stderr 上打印其错误。
当前的包装器脚本,如果两者都可以正常工作,mycommand并且other-command由于-e切换而失败并退出状态 != 0 :
#!/bin/bash -ex
mycommand --some-argument /some/path/to/file
other-command --other-argument /some/other/file
Run Code Online (Sandbox Code Playgroud)
如何检查打印到 stderr 的任何内容(使主脚本失败)?这是我尝试过的:
将 stderr 重定向到 subshell stdin,例如:
mycommand 2> >(if grep .; then echo NOK; else echo OK; fi)
Run Code Online (Sandbox Code Playgroud)
这似乎工作正常,但是,我无法控制此处的主 shell 退出,即exit 1不会退出主程序。我也不能控制子外壳之外的变量来传播它的结果。我真的必须创建一个命名管道吗?
像这个答案一样设置额外的文件描述符。
对我来说看起来不是很优雅,真的。
一些“要求”:
所以它应该表现得像一个包装器,只以不干净的状态退出,保留打印输出。
我只是希望有更优雅的东西来检查 stderr 中的任何内容。抨击是可以接受的。
我正在尝试远程运行脚本并使用其标准输出来填充变量。我这样做是为了避免临时文件。
这是我正在尝试的模式:
var=$(bash <(curl -fsSkL http://remote/file.sh))
echo "var=${var}"
Run Code Online (Sandbox Code Playgroud)
我正在测试这种模式而不curl使用cat:
var=$(bash <(cat ./local/file.sh))
echo "var=${var}"
Run Code Online (Sandbox Code Playgroud)
就语法而言,这应该是相同的。 ./local/file.shcontains echo hello,所以我希望var包含 value hello,但唉,执行上述结果如下:
var=$(bash <(curl -fsSkL http://remote/file.sh))
echo "var=${var}"
Run Code Online (Sandbox Code Playgroud)
如何在不使用临时文件的情况下实现我的目标?
这个问题与其他问题很接近 -我可以从使用 $(command) 启动的子 shell 中获取退出代码吗?
但是,我发现没有解决方案可以让我在使用 local 和 eval 时从子 shell 获取退出代码,如本例所示...
test() {
> local WHY="$(eval "echo 'test'"; exit 3)"; echo $?
> }
test
0
Run Code Online (Sandbox Code Playgroud) foo() {
if [[ something ]]; then
echo "The foo function was called directly."
else
echo "The foo function was invoked via command substitution."
fi
}
Run Code Online (Sandbox Code Playgroud)
直接调用 foo:
foo
foo 函数被直接调用。
通过命令替换调用 foo:
a=$(foo) || exit 1
echo "${a}"
Run Code Online (Sandbox Code Playgroud)
foo 函数是通过命令替换调用的
有什么办法可以做到这一点吗?
我有一个运行良好的脚本,但按系列运行。
我想让脚本从文本文件中获取每一行并在子 shell 中运行/生成该行,然后移至下一行,依此类推。
我需要子 shell 有两个原因:
首先,让作业并行运行而不是串行运行,从而使其运行速度更快。
其次,监视给定命令的输出并从远程系统返回退出代码。
有谁知道我怎样才能做到这一点?
作为一点背景知识,文本文件的每一行都是在远程系统上运行的 ssh 命令的集合,其中包含从用户输入和另一个输入文件收集的选项、函数,因此脚本生成的输出中的每一行都是一个独立的服务器的命令。
我通过动作调用脚本/bin/bash $temp_file。
脚本示例类似于:
sshpass -p <PASSWORD> ssh -o StrictHostKeyChecking=no -p 22 USER@HOST.COM 'cat /etc/hostname ;echo 'START';echo `date +%Y-%m-%d` ; echo <PASSWORD> |sudo -S yum update -y; cat /etc/hostname ;echo 'FINISH';echo `date +%Y-%m-%d` ;echo '';echo ''
Run Code Online (Sandbox Code Playgroud)
这只是一个示例,要运行的命令(例如yum update -y我在这里使用的 with echos 和 date)将被替换为单个命令或使用;或$$来分隔它们。
我知道该行中有很多字符可能会导致问题。
因此,如果我输入如下命令,PID 4920子 shell 就会创建一个子进程 ( )。
linuxprobe@DESKTOP-TP0G72N:~$ (sleep 2;ps -f --forest;sleep 5)
UID PID PPID C STIME TTY TIME CMD
linuxpr+ 513 512 0 Feb17 pts/0 00:00:00 -bash
linuxpr+ 4920 513 0 01:35 pts/0 00:00:00 \_ -bash
linuxpr+ 4922 4920 0 01:35 pts/0 00:00:00 \_ ps -f --forest
Run Code Online (Sandbox Code Playgroud)
如果我输入如下命令,似乎没有创建子进程
linuxprobe@DESKTOP-TP0G72N:~$ (ps -f --forest)
UID PID PPID C STIME TTY TIME CMD
linuxpr+ 513 512 0 Feb17 pts/0 00:00:00 -bash
linuxpr+ 5511 513 0 01:45 pts/0 00:00:00 \_ ps …Run Code Online (Sandbox Code Playgroud) subshell ×10
bash ×5
shell ×3
exit ×2
linux ×2
variable ×2
command-line ×1
echo ×1
exit-status ×1
process ×1
shell-script ×1
stderr ×1
zsh ×1