Spec-Zone.ru › Ruby 3.4

class PTY

Parent:
Объект

Создаёт и управляет псевдотерминалами (PTY). Смотрите также en.wikipedia.org/wiki/Pseudo_terminal

PTY позволяет вам выделять новые терминалы с помощью ::open или запускать новый терминал со специфической командой с помощью ::spawn.

Пример

В этом примере мы изменим тип буферизации в команде factor, предполагая, что фактор использует stdio для буферизации stdout.

Если вместо PTY.open используется IO.pipe, этот код приводит к тупику, потому что stdout фактора полностью буферизован.

# start by requiring the standard library PTY
require 'pty'

master, slave = PTY.open
read, write = IO.pipe
pid = spawn("factor", :in=>read, :out=>slave)
read.close     # we dont need the read
slave.close    # or the slave

# pipe "42" to the factor command
write.puts "42"
# output the response from factor
p master.gets #=> "42: 2 3 7\n"

# pipe "144" to factor and print out the response
write.puts "144"
p master.gets #=> "144: 2 2 2 2 3 3\n"
write.close # close the pipe

# The result of read operation when pty slave is closed is platform
# dependent.
ret = begin
        master.gets     # FreeBSD returns nil.
      rescue Errno::EIO # GNU/Linux raises EIO.
        nil
      end
p ret #=> nil

Лицензия

© Авторское право 1998 года, Акинори Ито.

Этот программный код может быть свободно перераспределён для этой цели, полностью или частично, при условии, что вся эта информация об авторском праве включена во все копии этого программного обеспечения и приложений, а также производных от них.

Этот программный код предоставляется «как есть», без каких-либо гарантий, явных или подразумеваемых, относительно любых вопросов, включая, но не ограничиваясь, гарантией пригодности для конкретной цели или товарным видом, или полученными результатами от использования этого программного обеспечения.

Методы класса

check(pid, raise = false) → Process::Status или nil
check(pid, true) → nil или вызывает PTY::ChildExited
Исходный код
static VALUE
pty_check(int argc, VALUE *argv, VALUE self)
{
    VALUE pid, exc;
    rb_pid_t cpid;
    int status;
    const int flag =
#ifdef WNOHANG
        WNOHANG|
#endif
#ifdef WUNTRACED
        WUNTRACED|
#endif
        0;

    rb_scan_args(argc, argv, "11", &pid, &exc);
    cpid = rb_waitpid(NUM2PIDT(pid), &status, flag);
    if (cpid == -1 || cpid == 0) return Qnil;

    if (!RTEST(exc)) return rb_last_status_get();
    raise_from_check(cpid, status);

    UNREACHABLE_RETURN(Qnil);
}

Проверяет статус дочернего процесса, указанного pid. Возвращает nil, если процесс по-прежнему активен.

Если процесс не активен и raise было true, будет выброшено исключение PTY::ChildExited. В противном случае будет возвращён объект Process::Status.

pid

Идентификатор процесса для проверки

raise

Если true и процесс, идентифицируемый pid, больше не активен, будет выброшено исключение PTY::ChildExited.

getpty
Псевдоним для: spawn
open → [master_io, slave_file]
open {|(master_io, slave_file)| ... } → значение блока
Исходный код
static VALUE
pty_open(VALUE klass)
{
    int master_fd, slave_fd;
    char slavename[DEVICELEN];

    getDevice(&master_fd, &slave_fd, slavename, 1);

    VALUE master_path = rb_obj_freeze(rb_sprintf("masterpty:%s", slavename));
    VALUE master_io = rb_io_open_descriptor(rb_cIO, master_fd, FMODE_READWRITE | FMODE_SYNC | FMODE_DUPLEX, master_path, RUBY_IO_TIMEOUT_DEFAULT, NULL);

    VALUE slave_path = rb_obj_freeze(rb_str_new_cstr(slavename));
    VALUE slave_file = rb_io_open_descriptor(rb_cFile, slave_fd, FMODE_READWRITE | FMODE_SYNC | FMODE_DUPLEX | FMODE_TTY, slave_path, RUBY_IO_TIMEOUT_DEFAULT, NULL);

    VALUE assoc = rb_assoc_new(master_io, slave_file);

    if (rb_block_given_p()) {
        return rb_ensure(rb_yield, assoc, pty_close_pty, assoc);
    }

    return assoc;
}

Выделяет pty (псевдотерминал).

В форме с блоком, передаёт массив из двух элементов (master_io, slave_file) и возвращает значение блока из open.

Оба IO и File будут закрыты после завершения блока, если они ещё не были закрыты.

PTY.open {|master, slave|
  p master      #=> #<IO:masterpty:/dev/pts/1>
  p slave      #=> #<File:/dev/pts/1>
  p slave.path #=> "/dev/pts/1"
}

В форме без блока, возвращает массив из двух элементов, [master_io, slave_file].

master, slave = PTY.open
# do something with master for IO, or the slave file

Аргументы в обеих формах:

master_io

главный порт pty, как IO.

slave_file

ведомый порт pty, как File. Путь к устройству терминала доступен через slave_file.path

IO#raw! используется для отключения преобразования новых строк:

require 'io/console'
PTY.open {|m, s|
  s.raw!
  # ...
}
spawn([env,] command_line) { |r, w, pid| ... }
spawn([env,] command_line) → [r, w, pid]
spawn([env,] command, arguments, ...) { |r, w, pid| ... }
spawn([env,] command, arguments, ...) → [r, w, pid]
Исходный код
static VALUE
pty_getpty(int argc, VALUE *argv, VALUE self)
{
    VALUE res;
    struct pty_info info;
    char SlaveName[DEVICELEN];

    establishShell(argc, argv, &info, SlaveName);

    VALUE pty_path = rb_obj_freeze(rb_str_new_cstr(SlaveName));
    VALUE rport = rb_io_open_descriptor(
        rb_cFile, info.fd, FMODE_READABLE, pty_path, RUBY_IO_TIMEOUT_DEFAULT, NULL
    );

    int wpty_fd = rb_cloexec_dup(info.fd);
    if (wpty_fd == -1) {
        rb_sys_fail("dup()");
    }
    VALUE wport = rb_io_open_descriptor(
        rb_cFile, wpty_fd, FMODE_WRITABLE | FMODE_TRUNC | FMODE_CREATE | FMODE_SYNC,
        pty_path, RUBY_IO_TIMEOUT_DEFAULT, NULL
    );

    res = rb_ary_new2(3);
    rb_ary_store(res, 0, rport);
    rb_ary_store(res, 1, wport);
    rb_ary_store(res,2,PIDT2NUM(info.child_pid));

    if (rb_block_given_p()) {
        rb_ensure(rb_yield, res, pty_detach_process, (VALUE)&info);
        return Qnil;
    }
    return res;
}

Запускает указанную команду в новом выделенном pty. Также можно использовать псевдоним ::getpty.

Контролирующее tty команды устанавливается на ведомое устройство pty, и стандартный ввод/вывод/ошибки перенаправляются на ведомое устройство.

env — это необязательный хэш, который предоставляет дополнительные переменные окружения для запущенного pty.

# sets FOO to "bar"
PTY.spawn({"FOO"=>"bar"}, "printenv", "FOO") do |r, w, pid|
  p r.read #=> "bar\r\n"
ensure
  r.close; w.close; Process.wait(pid)
end
# unsets FOO
PTY.spawn({"FOO"=>nil}, "printenv", "FOO") do |r, w, pid|
  p r.read #=> ""
ensure
  r.close; w.close; Process.wait(pid)
end

command и command_line — это полные команды для выполнения, с учётом String. Любые дополнительные arguments будут переданы команде.

Возвращаемые значения

В форме без блока, возвращает массив размером три, [r, w, pid].

В форме с блоком эти же значения будут переданы в блок:

r

Чтение IO содержащий стандартный вывод и стандартные ошибки команды

w

Запись IO, являющийся стандартным вводом команды

pid

Идентификатор процесса для команды.

Очистка

Этот метод не выполняет очистку, например закрытие вводов-выводов или ожидания дочернего процесса, за исключением того, что процесс открепляется в форме с блоком, чтобы избежать превращения его в зомби (см. Process.detach). Любая другая очистка является обязанностью вызывающего кода. Если нужно ожидать pid, убедитесь, что вы закрыли как r, так и w, прежде чем делать это; выполнение в обратном порядке может привести к тупику на некоторых операционных системах.

Также алиасы: getpty

Ruby Core © 1993–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API