我有一个关于执行简单命令的简单问题。根据我的理解,当我们ls在交互式 shell 中键入命令时,
如果我的理解是正确的,我们在 shell 提示符下键入的一个简单命令会在子进程上执行,并且该命令的结果不会影响当前 shell 的环境。
如果是这样,那么内置命令cd呢?如果cd在子进程上执行并且不能影响当前shell的环境,那么如何更改当前shell的工作目录?
我引用了config.status生成的下一个代码片段configure。
if test ! -f "$as_myself"; then
{ { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
{ (exit 1); exit 1; }; }
fi
Run Code Online (Sandbox Code Playgroud)
在代码片段中,有什么作用{ (exit 1); exit 1; };?只exit在子shell中做什么的目的是什么?
Between the following alternatives...
with eval.
comd="ls"
eval "$comd"
Run Code Online (Sandbox Code Playgroud)with source /dev/stdin
printf "ls" | source /dev/stdin
Run Code Online (Sandbox Code Playgroud)with source /dev/stdin and ( ) or { }
( printf "ls" ) | source /dev/stdin
{ printf "ls"; } | source /dev/stdin
Run Code Online (Sandbox Code Playgroud)
(When we run printf in { }, is there any benefit other than not using subshell?)
What is the difference between them?
Which is preferred?
Which is the preferred way to run commands? () or {}?
在 shell 编程语言中,扩展和替换似乎可以在相同的上下文中互换。例如,Bash 参考手册、Bash Hackers Wiki等一些文档使用“扩展”一词来解释“shell 参数扩展”。然而,其他一些文件似乎更喜欢“替代”这个词。Advanced Bash-Scripting Guide使用参数替换。
在 shell 编程术语方面,“扩展”和“替换”之间有什么区别吗?
我们可以在冒号后使用 bash 的条件运算符和赋值运算符吗?
Bash 参考手册解释了算术运算符如下。
expr ? expr : expr= *= /= %= += -= <<= >>= &= ^= |=首先,这段代码似乎运行良好:
a=1; ((a? b=1 : 2 )) #seems to work
Run Code Online (Sandbox Code Playgroud)
但是当我在 之后使用赋值运算符时:,我得到了“尝试赋值给非变量”错误:
a=1; ((a? b=1 : c=1)) #attempted assignment to non-variable error
Run Code Online (Sandbox Code Playgroud)
为什么我们只能在冒号前使用赋值运算符?
这个问题与“当我们在 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; }'会有所帮助吗?
man bash 说,
A login shell is one whose first character of argument zero is a -, or
one started with the --login option.
Run Code Online (Sandbox Code Playgroud)
当我们调用mintty -Cygwin等终端时,我们可以看到-$0 中的单个连字符 ( )。
$ echo $0
-bash
Run Code Online (Sandbox Code Playgroud)
但是如果我们调用带有--login选项的登录shell ,我们就看不到-.
$bash --login
$echo $0
bash
Run Code Online (Sandbox Code Playgroud)
我的问题是:
的作用是-什么?虽然我们在登录 shell 上看不到它被调用--login,但我们可以通过查询相关的 shell 选项来检查 shell 的类型,例如shopt -q login_shell. 它是做什么用的?
如果有重要作用-,为什么我们在用 调用的登录shell 上看不到它--login?
我们如何手动调用零参数以 开头的登录shell -?
其他 shell 也是这种情况,例如 zsh、csh?
此代码片段来自Advanced Bash Scripting Guide。
# Redirecting only stderr to a pipe.
exec 3>&1 # Save current "value" of stdout.
ls -l 2>&1 >&3 3>&- | grep bad 3>&- # Close fd 3 for 'grep' (but not 'ls').
# ^^^^ ^^^^
exec 3>&- # Now close it for the remainder of the script.
# Thanks, S.C.
Run Code Online (Sandbox Code Playgroud)
注释解释了代码只为“grep”关闭 fd 3。但关闭 fd 3 两次。为什么我们需要这样做?像这样为“grep”只关闭一次 fd 3 是错误的吗?
ls -l 2>&1 >&3 | grep bad 3>&-
Run Code Online (Sandbox Code Playgroud) shell ×7
bash ×5
shell-script ×3
process ×2
subshell ×2
arithmetic ×1
command-line ×1
configure ×1
login ×1
terminology ×1