小编Axe*_*ton的帖子

声明命令和外壳扩展

我偶然发现了以下bash行为,这对我来说有点出乎意料。

# The following works
$ declare bar=Hello                               # Line 1
$ declare -p bar                                  # Line 2
declare -- bar="Hello"
$ foo=bar                                         # Line 3
$ declare ${foo}=Bye                              # Line 4
$ declare -p bar                                  # Line 5
declare -- bar="Bye"
# The following fails, though
$ declare -a array=( A B C )                      # Line 6
$ declare -p array                                # Line 7
declare -a array=([0]="A" [1]="B" [2]="C")
$ foo=array                                       # Line 8
$ declare -a …
Run Code Online (Sandbox Code Playgroud)

bash declare

5
推荐指数
1
解决办法
350
查看次数

保存后恢复光标位置

使用简单的ANSI 转义序列应该可以保存和恢复光标位置

ANSI 转义序列允许您在屏幕上随意移动光标。这对于 shell 脚本生成的全屏用户界面更有用,但也可以在提示中使用。运动转义序列如下:

  • [...]
  • 保存光标位置:\033[s
  • 恢复光标位置:\033[u

来源:Bash Prompt HOWTO:光标移动

然而,这个 ANSI 序列似乎只恢复光标的水平位置。例如:

$ printf 'Doing some task...\e[s\n\nMore text\n\e[udone!\n\n\n'
Doing some task...

More text
                  done!


$
Run Code Online (Sandbox Code Playgroud)

其中done!水平位于正确位置,但垂直方向不正确(在恢复的意义上是正确的)。

  1. 我错过了什么吗?你能重现这个吗?!
  2. 这是预期的行为吗?如果是这样,我将如何done!在之后打印task...
  3. 如果这种情况不应该发生,那么这种行为可能是由我的环境中的某些东西间接触发的吗?

我搜索并阅读了许多问题,但我没有找到任何关于我经历过的这种行为的信息。tput实际上, via也会发生同样的情况

$ printf 'Doing some task...'; tput sc; printf '\n\nMore text\n'; tput rc; printf 'done!\n\n\n'
Run Code Online (Sandbox Code Playgroud)

bash terminal cursor

4
推荐指数
1
解决办法
3348
查看次数

Bash:什么时候完全释放 PID?

免责声明:这个问题出现的时间比预期的要长得多。我把它分成 5 个子问题。在打开之前,我真的很想弄清楚自己的想法,但是此刻太多的方面让我感到困惑。


为了阐明我对如何以可靠的方式正确处理 Bash 中的进程的想法,我偶然发现了这篇 Greg 的 Wiki 文章。在那里,而不是在开始时,有这样的声明

如果您仍处于启动您想要对其进行处理的子进程的父进程中,那就太完美了。您可以保证 PID 是您的子进程(死的或活的),原因如下所述。您可以使用kill它来发出信号、终止它,或者只是检查它是否仍在运行。您可以使用wait等待它结束或在它结束时获取其退出代码。

在页面的末尾,找到了下面解释的上述原因

每个 UNIX 进程也有一个父进程。此父进程是启动它的进程,但init如果父进程在新进程结束之前结束,则可以更改为该进程。(也就是说,init将选择孤立进程。)理解这种父/子关系至关重要,因为它是 UNIX 中可靠进程管理的关键。进程wait终止后,进程的 PID 将永远不会被释放以供使用,直到父进程为 PID 查看它是否结束并检索其退出代码。如果父进程结束,进程将返回到init,它会为您执行此操作。

这是一个主要的原因,重要的是:如果父进程管理其子进程,也可以是绝对肯定的是,即使孩子过程中的模具,没有其他新的进程可能会意外地回收子进程的PID,直到父进程已经wait编为PID并注意到孩子死了。这让父进程保证它为子进程拥有的 PID 将始终指向该子进程,无论它是活着的还是“僵尸”。没有其他人有这种保证。

不幸的是,这种保证不适用于 shell 脚本。Shell 积极地获取它们的子进程并将退出状态存储在内存中,在调用wait. 但是因为孩子调用之前就已经被收割了wait,所以没有僵尸来持有PID。内核可以自由地重用该 PID,而您的保证已被违反。


到目前为止,我已多次阅读以上段落,但我仍然不确定我是否正确理解了其背后的信息。

问题 1:从第二个长引用,特别是从它的最后一段,我会得出结论,在 shell(我只对 Bash 感兴趣)脚本中,我不能 100% 确定我存储在变量中的 PID 仍然指的是我启动了后台进程,因为它可能被内核重用于任何其他进程(甚至不是子进程)。这样对吗?上述保证适用于系统中的哪些地方? …

bash process background-process

3
推荐指数
1
解决办法
268
查看次数

标签 统计

bash ×3

background-process ×1

cursor ×1

declare ×1

process ×1

terminal ×1