Ruby:如何设置前台终端进程组(posix tcsetpgrp)?

Ruby:如何设置前台终端进程组(posix tcsetpgrp)?,ruby,posix,Ruby,Posix,我知道这已经被问到了很多不同的方法,我能够用C和Python实现我想要的,但是我需要用Ruby来实现这一点;然而,我没有在任何文档或谷歌上看到对tcsetpgrp的支持。我甚至尝试为posix函数创建一个C包装器,但找不到 简而言之,我想向Ruby脚本添加代码,该脚本将: 将自身(或者更好地说,它创建的子流程)置于与其父进程(如posix setpgrp)不同的进程组中 使这个新的过程组在控制终端(如posix tcsetpgrp)中成为前台 我将包括我的Python代码,这可能会更好地解释这一

我知道这已经被问到了很多不同的方法,我能够用C和Python实现我想要的,但是我需要用Ruby来实现这一点;然而,我没有在任何文档或谷歌上看到对tcsetpgrp的支持。我甚至尝试为posix函数创建一个C包装器,但找不到

简而言之,我想向Ruby脚本添加代码,该脚本将:

  • 将自身(或者更好地说,它创建的子流程)置于与其父进程(如posix setpgrp)不同的进程组中
  • 使这个新的过程组在控制终端(如posix tcsetpgrp)中成为前台
  • 我将包括我的Python代码,这可能会更好地解释这一点,并说明这项任务应该多么简单。我不是在寻找一个完整的解决方案,但更重要的是,Ruby 2.6.5中缺少了一个tcsetpgrp解决方案。。。是否有不同的功能或方法?如何创建一个包装器来调用手册页中描述的posix函数

    提前谢谢

    tcgetpgrp:

    
    NAME
           tcgetpgrp, tcsetpgrp - get and set terminal foreground process group
    
    SYNOPSIS
           #include <unistd.h>
    
           pid_t tcgetpgrp(int fd);
    
           int tcsetpgrp(int fd, pid_t pgrp);
    

    这是一个非常直接的python代码逐行翻译

    由于ruby没有实现
    tcsetpgrp
    ,最简单的解决方案是使用gem绑定到它,通过
    gem安装ffi
    或将ffi添加到项目
    Gemfile

    要求“外国金融机构”
    #这是我们的FFI与我们的系统libc的绑定。
    模块C
    扩展FFI::库
    外国金融机构自由党'c'
    #‘int tcsetpgrp(int,pid)’。
    #显然,glibc将pid_t定义为int,所以使用它。
    #这可能与系统/操作系统有关!
    附加函数:tcsetpgrp,[:int,:int],:int
    结束
    Process.setpgrp
    prev=信号陷阱('sigttoo','IGNORE')
    tty=File.open('/dev/tty',r')
    rc=C.tcsetpgrp(tty.fileno,Process.getpgrp)
    信号陷阱('SIGTTOU',上一个)
    关闭
    
    参考资料:


    Bingo,
    ffi_lib'c'
    就是我丢失的那块。让我试试这个,看看是否有效。非常感谢您的快速回复,John!
    def App.become_tty_fg
      '''This function, when used like:
      suprocess.Popen(..., preexec_fn=become_tty_fg)
      will force the child into a new process group and
      also force the child process group to be the foreground process group in the
      controlling terminal. The affect will be that that only the child will
      receive a ctrl-c generated SIGNINT because the parent is now backgrounded in a
      different process group and the child process group is foreground.  Signals
      reach all memebers of a proces group but ctrl-c originates in the foreground
      process group, so the child must be foreground in the terminal and in its own
      process group to protect the parent from an ctrl-c generated SIGINT.
      '''
      # create new process group for the child and put it in it.
      os.setpgrp()
    
      # Supress handling of SIGTTOU which would otherwise stop the
      # child proc when the terminal process group is changed.
      # The return value is the current handler for SIGTTOU.
      hdlr = signal.signal(signal.SIGTTOU, signal.SIG_IGN)
    
      # Need the terminal handle to use tcsetpgrp()
      tty = os.open('/dev/tty', os.O_RDWR)
    
      # change the foreground process in the terminal to the child
      os.tcsetpgrp(tty, os.getpgrp())
    
      # restore handling of SIGTTOU in case the child needs to be stopped (ctrl-z)
      signal.signal(signal.SIGTTOU, hdlr)
      tty.close()