jjzjj

bash - exec.Command 卡在包含 nohup 的 Bash 脚本上

coder 2024-07-06 原文

当我使用 Go 的 exec.Command{} 时执行一些包含 nohup 的 bash 脚本,它将永远挂起。

我不知道ping和ifconfig有什么区别。我尝试重定向标准输入 ( < /dev/null )、标准输出 ( > /dev/null ) 和标准错误 ( 2> /dev/null ) 以及它们的组合,其中一些有效,一些无效。

当我使用 sh 时执行脚本,它会立即结束。

Go 代码:

package main

import (
    "fmt"
    "os/exec"
)

func main() {
    cmd := exec.Command("sh", "a.sh")
    out, err := cmd.Output() // Or cmd.CombinedOutput()
    fmt.Println(string(out), err)
}

Bash 脚本 (a.sh):

#!/bin/bash

# hangs
#nohup ping localhost &

# dot not hang
nohup ifconfig &

最佳答案

(转换评论,修复故障,回答)

这里使用nohup主要是一个red herring .真正的问题是 ping 永远不会完成。但是,nohup 有一些额外的怪异之处,如果您从交互式终端运行这两组命令,您会发现这一点:

$ nohup echo foo
nohup: ignoring input and appending output to 'nohup.out'
$ cat nohup.out
foo
$ 

对比:

$ nohup echo foo </dev/null 2>&1 | cat 
foo
$ 

注意第一个如何打印奇怪的消息,然后输出 foo 到一个文件;第二个没有,然后输出 foo 出现在常规输出流中。这是因为 POSIX 规定 nohup 应该在适当时执行这些重定向。1 当使用 exec.Cmdcmd.Output<>执行重定向。

在操作系统级别,在 Linux 或其他类 Unix 系统上,exec 代码创建一个 OS pipe object通过它调用的命令可以将输出发送回 Go 运行时。 (它的 stderr 输出可能有一个单独的管道,或者两个可能都被定向到一个管道,这取决于您如何运行命令;参见 https://golang.org/src/os/exec/exec.go#L280。)这个管道最终被传递给 ping,这样 ping 就可以一直在那里写入输出,只要它愿意。

shell 本身 退出,因为命令 nohup ping localhost & 在后台运行。但是,ping 仍然对管道对象具有写入权限,因此 Go 运行时会继续调用 OS read 代码,直到管道关闭——这永远不会。如果管道曾经关闭,Go 运行时将接收 EOF 并调用 wait 系统调用来收集 shell 的退出状态,但这种情况永远不会发生。

重定向 ping 的输出,使 shell 本身具有对管道的唯一写入权限,应该会导致管道在 shell 本身退出时立即关闭。

(一些 shell 可能有一个内置的 nohup,它可能会表现得很奇怪,尤其是在存在重定向的情况下。对于一些特别古老的 shell 来说是这样。)


1参见https://pubs.opengroup.org/onlinepubs/9699919799/utilities/nohup.html完整的细节。如果输入是终端,并且输出和 stderr 是终端,Linux 变体会重定向 stdin 以及 stdout 和 stderr。 FreeBSD 变种只重定向 stdout 和/或 stderr。 “is a terminal”测试基于C语言isatty函数,与https://godoc.org/golang.org/x/crypto/ssh/terminal#IsTerminal做同样的事情。 .

关于bash - exec.Command 卡在包含 nohup 的 Bash 脚本上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57643867/

有关bash - exec.Command 卡在包含 nohup 的 Bash 脚本上的更多相关文章

  1. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  2. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  3. ruby - 如何在 Ruby 中拆分参数字符串 Bash 样式? - 2

    我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"

  4. ruby-on-rails - 独立 ruby​​ 脚本的配置文件 - 2

    我有一个在Linux服务器上运行的ruby​​脚本。它不使用rails或任何东西。它基本上是一个命令行ruby​​脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg

  5. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  6. postman——集合——执行集合——测试脚本——pm对象简单示例02 - 2

    //1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json

  7. ruby-on-rails - 使用包含多个关联和单独的条件 - 2

    我的Gallery模型中有以下查询:media_items.includes(:photo,:video).rank(:position_in_gallery)我的图库模型有_许多媒体项,每个都有一个照片或视频关联。到目前为止,一切正常。它返回所有media_items包括它们的photo或video关联,由media_item的position_in_gallery属性排序。但是我现在需要将此查询返回的照片限制为仅具有is_processing属性的照片,即nil。是否可以进行相同的查询,但条件是返回的照片等同于:.where(photo:'photo.is_processingIS

  8. ruby - 确定 ruby​​ 脚本是否已经在运行 - 2

    有没有一种简单的方法可以判断ruby​​脚本是否已经在运行,然后适本地处理它?例如:我有一个名为really_long_script.rb的脚本。我让它每5分钟运行一次。当它运行时,我想看看之前运行的是否还在运行,然后停止第二个脚本的执行。有什么想法吗? 最佳答案 ps是一种非常糟糕的方法,并且可能会出现竞争条件。传统的Unix/Linux方法是将PID写入文件(通常在/var/run中)并在启动时检查该文件是否存在。例如pid文件位于/var/run/myscript.pid然后你会在运行程序之前检查它是否存在。有一些技巧可以避免

  9. ruby - 我怎样才能只写一次 "Text"并同时检查 path_info 是否包含 'A' ? - 2

    -if!request.path_info.include?'A'%{:id=>'A'}"Text"-else"Text"“文本”写了两次。我怎样才能只写一次并同时检查path_info是否包含“A”? 最佳答案 有两种方法可以做到这一点。使用部分,或使用content_forblock:如果“文本”较长,或者是一个重要的子树,您可以将其提取到一个部分。这会使您的代码变干一点。在给出的示例中,这似乎有点矫枉过正。在这种情况下更好的方法是使用content_forblock,如下所示:-if!request.path_info.inc

  10. ruby - ruby 脚本可以预编译成二进制文件吗? - 2

    我正在开发一个Ruby脚本,需要在没有Ruby解释器的情况下部署到系统上。它将需要在使用ELF格式的FreeBSD系统上运行。我知道有一个ruby​​2exe项目可以编译在Windows上运行的ruby​​脚本,但是在其他操作系统上这样做容易吗?甚至可能吗? 最佳答案 您是否检查过Rubinius或JRuby是否允许您预编译您的代码? 关于ruby-ruby脚本可以预编译成二进制文件吗?,我们在StackOverflow上找到一个类似的问题: https://

随机推荐