Системный вызов без вызова оболочки в R
В базе R есть 3 основных механизма для вызова системной команды: system
, system2
и shell
(который, как представляется, имеет manpage с system
). Ни один из них не обеспечивает очень надежный кросс-платформенный способ запускать системную команду без сбоя оболочки, и если оболочка вмешивается, нам нужно беспокоиться о атаках, связанных с атакой оболочки, о том, чтобы убедиться, что цитата правильная и так далее.
Некоторые языки обеспечивают прямой доступ к функции execvp
уровня C (например, Perl system PROGRAM LIST
), что очень полезно, когда я хочу убедиться что строки в массиве - это точно строки, которые подпроцесс увидит в своих аргументах, не оглядываясь на подходящую кавычку для встроенных пробелов, кавычек и т.д. и беспокоясь о том, что они будут делать на разных платформах и разных версиях оболочек.
Есть ли аналогичный механизм системного вызова без оболочки, доступный в R, возможно, где-то в пакете CRAN? И/или есть ли какой-либо аппетит для создания такого механизма, если он еще не существует?
Ответы
Ответ 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, чтобы ничего не показывать для него.