аргументы ограничивают php exec () скриптом bash
Проверка того, сколько времени потребуется, чтобы передать 50000 аргументов из php в сценарий bash, показала, что я не могу передать даже 1000 аргументов из php в сценарий bash за один раз, если я не могу?
PHP:
$array = fetch_results_from_working_pool_temp_table (); $outputfile = "/var/www/html/outputFile";
$pidfile = "/var/www/html/pidFile"; $id = "";
$array_check=array(); foreach ( $array as $row => $column ) {
$id .= $column ['id'];
$id .= " "; } $cmd = "sudo /bin/bash /var/www/html/statistics/pass_all.sh {$id}"; exec( sprintf ( "%s >> %s 2>&1 & echo $! >> %s", $cmd, $outputfile, $pidfile ) ); bash: #!/bin/bash for ip in "$@"
do
echo "${ip}"
done
Итак, мой php передает аргументы в bash , bash печатает в outputFile вместе с любыми ошибками. pidfile будет содержать pid процесса, запущенного с помощью этого exec. Команда даже не выполняется, потому что я не вижу запущенного процесса. Есть ли ограничение на переданные аргументы в exec? или из PHP или в оболочке Linux? Я использую php 5.4 и Linux Redhat 7. Я хочу запускать процессы с использованием параллельного GNU, но поскольку PHP является однопоточным (есть библиотеки для передачи этого, но я бы предпочел этого избежать). Может быть, я мог бы как-то передать это в текстовый файл и выполнить сценарий, который извлекает из этого текстового файла? Помогите!
** Обновление: ограничения моей машины: ** #getconf ARG_MAX 2097152 #ulimit -a размер основного файла (блоки, -c) 0 размер сегмента данных (кбайт, -d) неограничен приоритет планирования (-e) 0 размер файла (блоки, -f) неограничен ожидающие сигналы (-i) 256634 максимальная заблокированная память (кбайт, -l) 64 максимальный размер памяти (кбайт, -m) неограничен открыть файлы (-n) 1024 размер канала (512 байт, -p) 8 Очереди сообщений POSIX (байты, -q) 819200 приоритет реального времени (-r) 0 размер стека (кбайт, -с) 8192 время процессора (секунды, -t) неограниченно максимальное количество пользовательских процессов (-u) 4096 виртуальная память (кбайт, -v) без ограничений файловые блокировки (-x) неограниченно
Ответы
В большинстве систем ядро ограничивает размер аргументов execve()системного вызова (аргументы командной строки + переменные среды). В Linux ограничение связано с максимальным размером стека, хотя обычно вы получаете не менее 2 МБ для ограничения размера стека по умолчанию в 8 МБ. Он также ограничивает один аргумент до 128 КБ, см., Например, Есть ли максимум для расширения имени файла bash (подстановка), и если да, то какой? и увеличить ограничение на 128 КБ для переменных среды в Linux.
Если PHP запускается sh -c 'command line'при вызове, exec("command line")то аргумент для -cвполне может превышать этот предел в 128 КБ. Тот факт, что командная строка впоследствии разделяется оболочкой на отдельные слова, не поможет.
Когда у вас столько аргументов, вы хотите передать их GNU Parallel через стандартный ввод (stdin) или через файлы.
Я бы сделал что-то вроде (непроверено):
$f = popen("parallel","w"); fwrite($f,$commands); close ($f);
Таким образом вы сможете избежать временного файла.
Итак, с вашей помощью вот мое решение: PHP:
function scan_targets() {
$targetsFile= "[absolute path to the file]/targets"; $array_with_targets = fetch_from_db (); //function that gets me all the targets
$outputfile = "[absolute path to the file]/outputFile"; //output from parallel script $pidfile = "[absolute path to the file]/pidFile"; //PID of the process
$target = ""; foreach ( $array_with_targets as $row => $column ) {
$id .= $column ['id'];
$id .= " "; } file_put_contents($targetsFile, $ip) ; $cmd = "/bin/bash [absolute path to the file]/pass_targets.sh";
exec( sprintf ( "%s >> %s 2>&1 & echo $! >> %s", $cmd, $outputfile, $pidfile ) );
БАШ:
#!/bin/bash
#appending arguments to the command
targets_array=()
IFS=" "
while read -r field || [ -n "$field" ]; do targets_array+=("$field")
done <[absolute path to the file]/targets
parallel bash [absolute path to the file]/check.sh ::: $targets_array
Вы также можете запустить параллель с параметром -Dall, чтобы лучше понять, что происходит. Мне удалось просканировать почти 40 000 хостов за 7 часов. Веб-сервер добавил все цели в файл за секунды, и, когда мой exec запускает фоновый процесс, ему не нужно ждать результата (мы выводим его в файл).
И сценарий check.sh также обновляет запись базы данных Mariadb для конкретной цели по мере продвижения.