Как проверить, не выполнена ли команда, использованная для pipe ()? - PullRequest
1 голос
/ 06 июня 2019

Скажем, я написал функцию компрессора вида:

compress <- function(text, file){
    c <- paste0("gzip -c > ",shQuote(file))
    p <- pipe(c, open = "wb")
    on.exit(close(p))
    writeLines(text, p)
}

Теперь я могу сжать строки следующим образом:

compress("Hello World", "test.gz")
system("zcat test.gz")
## Hello World

Однако, как я могу проверить, что программа gzip, вызываемая pipe(), успешно выполняется?

например.

compress("Hello World", "nonexistent-dir/test.gz")
## sh: nonexistent-dir/test.gz: No such file or directory

приводит к сообщению об ошибке, напечатанному на STDERR, но я не могу создать ошибку R. Программа просто продолжается без сохранения моего текста.

Я знаю, что я могу просто проверить наличие целевого файла в этом примере. Но есть много возможных ошибок, таких как конец дискового пространства, программа не найдена, какая-то библиотека отсутствует, программа была найдена , но интерпретатор ELF не был и т. Д. Я просто не могу вспомнить ни одного способ проверить на все возможные ошибки.

Я искал страницу справки ?pipe, но не смог найти подсказки.

Как подход, специфичный для UNIX, я пытался перехватить сигнал SIGPIPE, но не смог найти способ сделать это. Вопросы переполнения стека по этой теме остаются без ответа [1] [2]

Как проверить код завершения или преждевременное завершение программы, вызванной с помощью pipe()?

1 Ответ

0 голосов
/ 07 июня 2019

Я не нашел решения с помощью pipe(), но пакет processx имеет решение. Сначала я создаю внешний процесс как фоновый процесс, получаю соединение с ним и пишу в это соединение.

Прежде чем начать писать, я проверяю, запущен ли процесс. После того, как все написано, я могу проверить код завершения программы.

library(processx)
p <- process$new("pigz","-c",stdin="|", stdout = "/tmp/test.gz")
if(!p$is_alive()) stop("Subprocess ended prematurely")
con <- p$get_input_connection()
# Write output
conn_write(con, "Hello World")
close(con)
p$wait()
if(p$get_exit_status() != 0) stop("Subprocess failed")
system("zcat /tmp/test.gz")
...