出于与此问题无关的某些原因,我不是直接而是通过单独的子 shell 下的命令替换和在后台在 bash 脚本中运行 Java 服务器。目的是让子命令返回 Java 服务器的进程 ID 作为其标准输出。有问题的片段如下:
launch_daemon()
{
/bin/bash <<EOF
$JAVA_HOME/bin/java $JAVA_OPTS -jar $JAR_FILE daemon $PWD/config/cl.yml <&- &
pid=\$!
echo \${pid} > $PID_FILE
echo \${pid}
EOF
}
daemon_pid=$(launch_daemon)
echo ${daemon_pid} > check.out
34056 34056
mypid=$(echo ${daemon_pid} | awk '{ gsub(" +.*",""); print $0 }')
最佳答案
按照@WilliamPursell 的提示,我在 bash 源代码中跟踪了这一点。老实说,我不知道这是否是一个错误;我只能说,这似乎是与可疑用例的不幸交互。
TL;DR:您可以通过删除 <&- 来解决问题从脚本。
闭幕 stdin充其量是有问题的,不仅仅是因为@JonathanLeffler 提到的原因(“程序有权拥有一个开放的标准输入。”),更重要的是因为 stdin bash 正在使用进程本身并在后台关闭它会导致竞争条件。
为了了解发生了什么,请考虑以下相当奇怪的脚本,它可能被称为 Duff's Bash Device,除了我不确定 Duff 是否会批准:(此外,正如所介绍的,它不是那么有用。但是某个地方的某个人已经在一些 hack 中使用过它。或者,如果没有,他们现在会看到它。)
/bin/bash <<EOF
if (($1<8)); then head -n-$1 > /dev/null; fi
echo eight
echo seven
echo six
echo five
echo four
echo three
echo two
echo one
EOF
bash和 head双方都要准备好分享stdin ,包括共享文件位置。这意味着 bash需要确保它刷新其读取缓冲区(或不刷新),以及 head需要确保它返回到它使用的输入部分的末尾。bash 通过将 here-documents 复制到临时文件来处理它们。如果它使用管道,则 head 不可能向后查找。)head 会发生什么?曾在后台运行?答案是,“一切皆有可能”,因为 bash和 head正在竞相从同一个文件描述符中读取数据。运行 head在后台将是一个非常糟糕的主意,甚至比至少可以预测的原始黑客更糟糕。/bin/bash <<EOF
cmd <&- &
echo \$!
EOF
cmd <&- & ) fork 出一个单独的进程(在后台运行)。在那个过程中,它关闭 stdin然后调用 cmd .stdin 读取命令。 (它的 stdin fd 还没有关闭,所以没关系),这导致它执行 echo命令。bash知道需要分享stdin ,所以它不能只是关闭 stdin .需要确保stdin的文件位置指向正确的位置,即使它实际上可能已经提前读取了缓冲区的输入值。所以就在它关闭之前 stdin ,它向后搜索到当前命令行的末尾。 [1]echo ,那么就没有问题了。如果它发生在前台 bash 使用 here-document 完成之后,也没有问题。但是如果它发生在 echo 工作时怎么办?在那种情况下,在 echo 之后完成,bash将重读 echo命令因为 stdin已倒带,echo将再次被执行。echo \${pid}被执行两次。其实也是造成echo \${pid} > $PID_FILE执行两次,但该行是幂等的;是不是echo \${pid} >> $PID_FILE ,双重执行将是可见的。<&-从服务器启动行开始,并可选择将其替换为 </dev/null如果您想确保服务器无法读取 stdin .case r_close_this: 的末尾。在函数中 do_redirection_internal在 redir.c ,大约在第 1093 行:check_bash_input (redirector);
close_buffered_fd (redirector);
lseek第二个是 close .我看到了使用 strace -f 的行为然后在代码中搜索看似合理的代码 lseek ,但我没有去调试器中验证的麻烦。
关于linux - Bash 命令替换给出奇怪的不一致输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20039771/
我想用ruby编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序
在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg
我正在为一个项目制作一个简单的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"
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
我从Ubuntu服务器上的RVM转移到rbenv。当我使用RVM时,使用bundle没有问题。转移到rbenv后,我在Jenkins的执行shell中收到“找不到命令”错误。我内爆并删除了RVM,并从~/.bashrc'中删除了所有与RVM相关的行。使用后我仍然收到此错误:rvmimploderm~/.rvm-rfrm~/.rvmrcgeminstallbundlerecho'exportPATH="$HOME/.rbenv/bin:$PATH"'>>~/.bashrcecho'eval"$(rbenvinit-)"'>>~/.bashrc.~/.bashrcrbenvversions
两个gsub产生不同的结果。谁能解释一下为什么?代码也可在https://gist.github.com/franklsf95/6c0f8938f28706b5644d获得.ver=9999str="\tCFBundleDevelopmentRegion\n\ten\n\tCFBundleVersion\n\t0.1.190\n\tAppID\n\t000000000000000"putsstr.gsub/(CFBundleVersion\n\t.*\.).*()/,"#{$1}#{ver}#{$2}"puts'--------'putsstr.gsub/(CFBundleVersio
我有一个问题。我想从另一个ruby脚本运行一个ruby脚本并捕获它的输出信息,同时让它也输出到屏幕。亚军#!/usr/bin/envrubyprint"Enteryourpassword:"password=gets.chompputs"Hereisyourpassword:#{password}"我运行的脚本文件:开始.rboutput=`runner`putsoutput.match(/Hereisyour(password:.*)/).captures[0].to_s正如您在此处看到的那样,存在问题。在start.rb的第一行,屏幕是空的。我在运行程序中看不到“输入您的密
假设我在Store的模型中有这个非常简单的方法:defgeocode_addressloc=Store.geocode(address)self.lat=loc.latself.lng=loc.lngend如果我想编写一些不受地理编码服务影响的测试脚本,这些脚本可能已关闭、有限制或取决于我的互联网连接,我该如何模拟地理编码服务?如果我可以将地理编码对象传递到该方法中,那将很容易,但我不知道在这种情况下该怎么做。谢谢!特里斯坦 最佳答案 使用内置模拟和stub的rspecs,你可以做这样的事情:setupdo@subject=MyCl
我有很多这样的文档:foo_1foo_2foo_3bar_1foo_4...我想通过获取foo_[X]的所有实例并将它们中的每一个替换为foo_[X+1]来转换它们。在这个例子中:foo_2foo_3foo_4bar_1foo_5...我可以用gsub和一个block来做到这一点吗?如果不是,最干净的方法是什么?我真的在寻找一个优雅的解决方案,因为我总是可以暴力破解它,但我觉得有一些正则表达式技巧值得学习。 最佳答案 我(完全)不懂Ruby,但类似这样的东西应该可以工作:"foo_1foo_2".gsub(/(foo_)(\d+)/
有这样的事吗?我想在Ruby程序中使用它。 最佳答案 试试这个http://csl.sublevel3.org/jp2a/此外,Imagemagick可能还有一些东西 关于ruby-是否有将图像文件转换为ASCII艺术的命令行程序或库?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/6510445/