【问题标题】:How to exit a Subshell如何退出子shell
【发布时间】:2016-12-28 21:39:16
【问题描述】:

基本上,我正在尝试退出包含循环的子shell。这是代码: `

stop=0
(    # subshell start
    while true           # Loop start
    do
        sleep 1           # Wait a second
        echo 1 >> /tmp/output         # Add a line to a test file

        if [ $stop = 1 ]; then exit; fi         # This should exit the subshell if $stop is 1
    done   # Loop done

) |         # Do I need this pipe?

    while true   
    do
        zenity --title="Test" --ok-label="Stop" --cancel-label="Refresh" --text-info --filename=/tmp/output --font=couriernew        # This opens Zenity and shows the file.  It returns 0 when I click stop.

      if [ "$?" = 0 ]        # If Zenity returns 0, then
      then
         let stop=1       # This should close the subshell, and
         break        # This should close this loop
      fi
    done        # This loop end
    echo Done

这不起作用。它从不说完成。当我按下停止时,它只会关闭对话框,但会继续写入文件。

编辑:我需要能够将变量从子 shell 传递到父 shell。但是,我需要继续写入文件并保持 Zenity 对话框出现。我该怎么做?

【问题讨论】:

  • 我想我不明白。有没有特殊的方法可以退出子shell?

标签: bash subshell zenity


【解决方案1】:

当你生成一个子 shell 时,它会创建当前 shell 的一个子进程。这意味着如果您在一个 shell 中编辑一个变量,它不会反映在另一个 shell 中,因为它们是不同的进程。我建议您将子shell 发送到后台并使用$! 获取其PID,然后在您准备好时使用该PID 杀死子shell。看起来像这样:

(                               # subshell start
    while true                  # Loop start
    do
        sleep 1                 # Wait a second
        echo 1 >> /tmp/output   # Add a line to a test file
    done                        # Loop done

) &                             # Send the subshell to the background

SUBSHELL_PID=$!                 # Get the PID of the backgrounded subshell

while true   
do
  zenity --title="Test" --ok-label="Stop" --cancel-label="Refresh" --text-info --filename=/tmp/output --font=couriernew        # This opens Zenity and shows the file.  It returns 0 when I click stop.

  if [ "$?" = 0 ]               # If Zenity returns 0, then
  then
     kill $SUBSHELL_PID         # This will kill the subshell
     break                      # This should close this loop
  fi
done                            # This loop end

echo Done

【讨论】:

  • 带括号的显式子shell没有用(并且可能不需要)。
  • 无论有无括号都可以使用;只需将 subshel​​l 发送到后台或循环即可。我个人更喜欢 subshel​​l,因为它清楚地表明了发送到后台的内容,而不是 while ......... done &,在我看来 done 正在后台处理(尽管它仍然有效)。是否有任何令人信服的理由省略括号?
  • 如果我在子shell中更改了一个变量,那么它会在主shell中更改吗?如果没有,那我如何在两者之间传递价值?
  • 省略括号的原因是为了提高效率:您明确生成了一个无关的子shell。如果您觉得需要一些分组语法,那么……使用分组语法:用大括号 {} 替换括号。
  • @Feldspar15523:不;一旦有了子外壳或管道(这意味着子外壳),单独的进程就不会干扰彼此的变量。您必须使用不同的 IPC 机制来告诉不同的进程该做什么。这可能是“创建一个文件 - 并让其他进程检查该文件是否存在”,但很难确保该文件被正确清理。您可能会从一个进程向另一个进程发送信号。等等。
猜你喜欢
  • 2012-03-12
  • 1970-01-01
  • 2020-01-14
  • 1970-01-01
  • 1970-01-01
  • 2012-06-23
  • 1970-01-01
  • 2011-01-05
  • 1970-01-01
相关资源
最近更新 更多