Подтвердить что ты не робот

Системный вызов без вызова оболочки в R

В базе R есть 3 основных механизма для вызова системной команды: system, system2 и shell (который, как представляется, имеет manpage с system). Ни один из них не обеспечивает очень надежный кросс-платформенный способ запускать системную команду без сбоя оболочки, и если оболочка вмешивается, нам нужно беспокоиться о атаках, связанных с атакой оболочки, о том, чтобы убедиться, что цитата правильная и так далее.

Некоторые языки обеспечивают прямой доступ к функции execvp уровня C (например, Perl system PROGRAM LIST), что очень полезно, когда я хочу убедиться что строки в массиве - это точно строки, которые подпроцесс увидит в своих аргументах, не оглядываясь на подходящую кавычку для встроенных пробелов, кавычек и т.д. и беспокоясь о том, что они будут делать на разных платформах и разных версиях оболочек.

Есть ли аналогичный механизм системного вызова без оболочки, доступный в R, возможно, где-то в пакете CRAN? И/или есть ли какой-либо аппетит для создания такого механизма, если он еще не существует?

4b9b3361

Ответ 1

Следующий код запускает команду в R без взаимодействия с оболочкой:

library(inline)
cfun <- cfunction(sig = signature(),
          includes = "#include <unistd.h>",
body = 'execl("/bin/date", "date", 0, 0, (char *)0);')
cfun()

Я уверен, что это плохая идея, так как я думаю, что это закончит процесс R после завершения выполненного процесса. Как насчет вилки?

Базовый пакет с параллельной функцией C mc_fork использует системную команду C fork для этого, используя каналы для межпроцессного взаимодействия. Я не знаю, как это будет летать на Windows с помощью MinGW, но поскольку он находится в базовом пакете, он, похоже, сработает, хотя, возможно, с совершенно другим механизмом нисходящего потока.

В источниках R для parallel я вижу в R-devel/src/library/parallel/src/fork.c

SEXP mc_fork(SEXP sEstranged)
...
pid = fork();

Ответ 2

Расширение на @Jack Wasey intuition:

library(inline)
cfun <- cfunction(sig = signature(),
          includes = "#include <unistd.h>",
body = '
pid_t fk = fork();
if (!fk) {
    execl("/bin/date", "date", 0, 0, (char *)0);
} else if (fk == -1) {
    perror("fork");
}
return(R_NilValue);
')
cfun()

... использует fork для предотвращения захвата текущего процесса (по крайней мере, в Linux), но безопасно возвращает вас в R, чтобы ничего не показывать для него.