AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 406689
Accepted
Philip Kirkbride
Philip Kirkbride
Asked: 2017-11-24 16:20:25 +0800 CST2017-11-24 16:20:25 +0800 CST 2017-11-24 16:20:25 +0800 CST

默默杀死subshel​​l?

  • 772

我想实现类似Q/A 的东西,但要使用子外壳。这是我正在尝试的一个最小示例:

(subshell=$BASHPID
  (kill $subshell & wait $subshell 2>/dev/null) &
sleep 600)

echo subshell done

我怎样才能使它只subshell done返回而不是:

./test.sh: line 4:  5439 Terminated              ( subshell=$BASHPID; ( kill $subshell && wait $subshell 2> /dev/null ) & sleep 600 )
subshell done

编辑:我在这里的术语可能是错误的,子shell是指第一组括号内的过程。

更新:

我想从实际程序中发布片段以获取上下文,上面是一个简化:

# If subshell below if killed or returns error connected variable won't be set
(if [ -n "$2" ];then

      # code to setup wpa configurations here

      # If wifi key is wrong kill subshell
      subshell=$BASHPID
      (sudo stdbuf -o0 wpa_supplicant -Dwext -i$wifi -c/etc/wpa_supplicant/wpa_supplicant.conf 2>&1 \
        | grep -m 1 "pre-shared key may be incorrect" \
        && kill -s PIPE "$subshell") &

      # More code which does the setup necessary for wifi

) && connected=true

# later json will be returned based on if connected is set
kill output
  • 3 3 个回答
  • 3614 Views

3 个回答

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2017-11-27T09:19:35+08:002017-11-27T09:19:35+08:00

    笔记:

    • wait $subshell不会工作,因为$subshell它不是你正在运行的进程的子进程wait。无论如何,你不会等待进程这样做,wait所以这并不重要。
    • kill $subshell将杀死子shell,但sleep如果子shell 在运行时已成功启动它,则不会kill。但是,您可以sleep在同一进程中运行exec
    • 您可以使用 SIGPIPE 而不是 SIGTERM 来避免该消息
    • 在列表上下文中不加引号的变量在bash.

    说了这么多,你可以这样做:

    (
      subshell=$BASHPID
      kill -s PIPE "$subshell" &
      sleep 600
    )
    echo subshell done
    

    (如果您想杀死而不仅仅是子shell,请替换sleep 60为,在这种情况下,您杀死它时甚至可能没有时间运行)。exec sleep 60killsleepsleep

    无论如何,我不确定你想用它来实现什么。

    sleep 600 &
    

    sleep如果这是您想要做的(或者(sleep 600 &)如果您想sleep从主 shell 隐藏该进程),这将是一种更可靠的在后台启动的方式

    现在用你的实际

    sudo stdbuf -o0 wpa_supplicant -Dwext -i"$wifi" -c/etc/wpa_supplicant/wpa_supplicant.conf
    

    命令,请注意,它sudo确实会产生一个子进程来运行该命令(如果只是因为它可能需要记录其状态或之后执行一些 PAM 会话任务)。stdbuf然而,将在同一个进程中执行,所以最后你将在的祖先wpa_supplicant中拥有三个进程(除了脚本的其余部分) :wpa_supplicant

    1. 子壳
    2. sudo 作为 1 岁的孩子
    3. wpa_supplicant(之前运行 stdbuf)作为 2 的孩子

    如果您杀死 1,则不会自动杀死 2。但是,如果您杀死 2,除非它带有无法拦截的 SIGKILL 之类的信号,否则它将杀死 3,因为sudo它会将收到的信号转发给它运行的命令.

    无论如何,这不是您要在这里杀死的子shell,它是 3 或至少 2。

    现在,如果它正在运行root而脚本的其余部分没有运行,您将无法如此轻松地杀死它。

    你需要kill做 as root,所以你需要:

    sudo WIFI="$wifi" bash -c '
      (echo "$BASHPID" &&
       exec stdbuf -o0 wpa_supplicant -Dwext -i"$WIFI" -c/etc/wpa_supplicant/wpa_supplicant.conf 2>&1
      ) | {
        read pid &&
          grep -m1 "pre-shared key may be incorrect" &&
          kill -s PIPE "$pid"
      }'
    

    这样,wpa_supplicant将在与$BASHPID子shell 相同的进程中运行,就像我们使用exec.

    我们通过管道获取 pid 并kill以 root 身份运行。

    请注意,如果您准备再等一会儿,

    sudo stdbuf -o0 wpa_supplicant -Dwext -i"$wifi" -c/etc/wpa_supplicant/wpa_supplicant.conf 2>&1 |
      grep -m1 "pre-shared key may be incorrect"
    

    下次它在消失后向该管道写入内容时会wpa_supplicant使用 SIGPIPE 自动终止(由系统执行,因此没有权限问题) 。grep

    某些 shell 实现不会等待sudoaftergrep返回(让它在后台运行,直到它获得 SIGPIPEd),并且使用bash,您也可以使用grep ... <(sudo ...)语法来执行此操作,其中bash不等待sudo之后grep返回。

    找到匹配项后,Grep 的更多信息退出缓慢?

    • 7
  2. J_H
    2017-11-27T09:18:42+08:002017-11-27T09:18:42+08:00

    子shell 是指一个shell 命令,它是某个shell 的子级,例如为bash -i您提供$提示的交互式登录shell 的子级。您不必在子 shell 中运行命令 - 您可以选择将其作为独立进程运行。听起来这可能是合适的,因为您不希望它的 stdout / stderr 弄乱进度条的外观,并且因为您不希望父 shell 报告甚至注意到其子进程的死亡。

    有一些标准工具可以实现这一点,例如daemonize和 nohup。(另请参见手册 页。)使用nohup可能是最好的选择。这是一个使用它来运行一个不创建 nohup.out 的简单程序的示例:

    $ nohup true 2>&1 > /dev/null &
    

    让您的程序或程序的包装脚本在 /tmp/my.pid 中记录其 PID —— bash 将其作为$$变量提供。那么带有进度条的监控过程就可以了

    $ kill `cat /tmp/my.pid`
    

    当它不再需要该程序进行任何处理时。或者,您可能更愿意将您的程序名称提供给killall.

    • 2
  3. Chris Hill
    2017-11-27T15:36:53+08:002017-11-27T15:36:53+08:00

    你可能正在寻找这个

    #!/bin/bash
    (subshell=$BASHPID
      (kill $subshell & wait $subshell 2>/dev/null) &
    sleep 600) &
    wait $! 2>/dev/null
    
    echo subshell done
    

    这里子shell被置于后台,然后父shell等待但等待输出发送到/dev/null。这会捕获Terminated消息。

    请注意,如果您更改等待以将输出捕获到文件,例如wait $! 2>wait_output,您将看到

     ./foo.sh: line 5:  1939 Terminated              ( subshell=$BASHPID; ( kill $subshell & wait $subshell 2> /dev/null ) & sleep 600 )
    

    表明这Terminated是来自父外壳。

    如果在杀死之前有一些活动,请进行一个小检查以查看它是否有效

    #!/bin/bash
    (subshell=$BASHPID
     (sleep 1; kill $subshell & wait $subshell 2>/dev/null) &
    sleep 600) & wait 2>wait_output
    
    echo subshell done
    

    此示例将在打印前暂停一秒钟subshell done。此示例还显示了如何在同一行进行后台处理和等待,例如& wait 2>wait_output. 我不确定这是否比带有wait $!.

    这里要注意的关键是Terminated消息来自顶级父 shell 作业控制。这就是看到子外壳终止并生成消息的原因。所以这就是你想要捕捉输出的地方。重定向wait命令输出会执行此操作。

    • 1

相关问题

  • 从后台进程退出脚本?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    JSON数组使用jq来bash变量

    • 4 个回答
  • Marko Smith

    日期可以为 GMT 时区格式化当前时间吗?[复制]

    • 2 个回答
  • Marko Smith

    bash + 通过 bash 脚本从文件中读取变量和值

    • 4 个回答
  • Marko Smith

    如何复制目录并在同一命令中重命名它?

    • 4 个回答
  • Marko Smith

    ssh 连接。X11 连接因身份验证错误而被拒绝

    • 3 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Marko Smith

    systemctl 命令在 RHEL 6 中不起作用

    • 3 个回答
  • Marko Smith

    rsync 端口 22 和 873 使用

    • 2 个回答
  • Marko Smith

    以 100% 的利用率捕捉 /dev/loop -- 没有可用空间

    • 1 个回答
  • Marko Smith

    jq 打印子对象中所有的键和值

    • 2 个回答
  • Martin Hope
    EHerman JSON数组使用jq来bash变量 2017-12-31 14:50:58 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Drux 日期可以为 GMT 时区格式化当前时间吗?[复制] 2017-12-26 11:35:07 +0800 CST
  • Martin Hope
    AllisonC 如何复制目录并在同一命令中重命名它? 2017-12-22 05:28:06 +0800 CST
  • Martin Hope
    Steve “root”用户的文件权限如何工作? 2017-12-22 02:46:01 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST
  • Martin Hope
    Cbhihe 将默认编辑器更改为 vim for _ sudo systemctl edit [unit-file] _ 2017-12-03 10:11:38 +0800 CST
  • Martin Hope
    showkey 如何下载软件包而不是使用 apt-get 命令安装它? 2017-12-03 02:15:02 +0800 CST
  • Martin Hope
    youxiao 为什么目录 /home、/usr、/var 等都具有相同的 inode 编号 (2)? 2017-12-02 05:33:41 +0800 CST
  • Martin Hope
    user223600 gpg —list-keys 命令在将私钥导入全新安装后输出 uid [未知] 2017-11-26 18:26:02 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve