命令替换为新的 shell 进程后如何继续执行脚本?

问题描述 投票:0回答:1

我有一个可执行的 ruby 脚本,如下所示:

example

#!/usr/bin/env ruby
at_exit do
  # Replace the currently running Ruby process with a new instance of the parent shell 
  exec(`ps -p #{Process.ppid} -o comm=`.chomp)
end

作为命令运行时它工作正常,但由于它用新的 shell 实例替换自身,因此它在脚本中不起作用,因为执行后没有命令。

如何修改 shell 脚本以便继续执行?

(我正在运行 shell 脚本,如下所示:

bash test.sh

我想实现的一些例子:

test.sh

#!/usr/bin/bash
./example && echo "How do i get here"

test1.sh

#!/usr/bin/bash
VAR=foo
$VAR ./example <argument> 

test2.sh

#!/usr/bin/bash
cd ~ && git clone https://github.com/gfxstrand/pycook
yes | ./example 

test3.sh

#!/usr/bin/bash
./example || echo "How do i get here"

请注意,我无法更改 ruby 脚本的行为——它必须在退出时用父 shell 的新实例替换自身。 (例外情况是用父 shell 的新实例替换 ruby 脚本的父进程的解决方案,这也足够了)

ruby linux bash shell
1个回答
0
投票

您想要的可以通过使用您控制的父进程而不是 bash 来实现。

由于

example
脚本将在退出时运行父进程,因此如果您控制父进程及其功能,您就可以做任何您喜欢的事情。

当前父进程是

bash
。你无法控制 bash,因此一旦将 Ruby 脚本替换为 bash,bash 将“挂起”,等待输入。

我们想要的是创建一个为我们运行

example
脚本的父进程,然后
example
脚本将运行我们的进程
at_exit
,然后我们可以告诉我们的进程退出,让其他一切都可以运行按照您的规格正常继续。

这是一个简单的 C 程序,我们将用作父进程。我们姑且称之为

runner.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char* argv[]) {
  // This is the magic trick which will prevent an infinite loop. 
  // Once the Ruby script launches runner.c without arguments, we just exit.
  if (argc == 1) {
    printf("Exit\n");
    exit(0);
  }

  // In order to be the parent for the Ruby script, we need to launch it as the child:
  if (fork() == 0){
    printf("I'm the child process.\n");

    // Run the example script as a child of the runner.c process
    // NOTE: You may need to adjust the Ruby path here
    execl("/usr/bin/ruby", "ruby", "example", (char *) 0);
    exit(0);
  } else {
    printf("I'm the parent.\n");

    // Wait here for the Ruby script to execute (wait for all children to exit).
    while (wait(NULL) > 0);
  }

  printf("runner.c is done.\n"); 
  return 0;
}

现在编译:

  gcc -o runner runner.c

然后像这样运行:

  ./runner dummy_arg

它应该按照您的意愿工作,使 Ruby 脚本正常退出。 现在你可以重写

test.sh
:

#!/usr/bin/bash
./runner dummy_arg && echo "How do i get here"

一切都应该有效。

© www.soinside.com 2019 - 2024. All rights reserved.