los argumentos limitan php exec () al script bash
Probando cuánto tiempo tomará pasar 50000 argumentos de php a un script bash, resulta que no puedo pasar ni siquiera 1000 argumentos de php a un script bash a la vez, a menos que pueda?
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
Entonces mi php pasa argumentos al bash , bash imprime al outputFile junto con cualquier error. pidfile contendrá el pid del proceso que se inició con este exec. El comando ni siquiera se está ejecutando porque no veo ningún proceso iniciado. ¿Hay algún límite para los argumentos pasados en exec? o desde PHP o en el shell de Linux? Estoy ejecutando php 5.4 y Linux Redhat 7. Quiero ejecutar procesos usando GNU en paralelo, pero debido a que PHP es de un solo hilo (hay bibliotecas para pasar esto, pero preferiría evitarlo). ¿Quizás podría pasarlo de alguna manera a un archivo de texto y ejecutarlo a un script que extraiga de este archivo de texto? ¡Ayuda!
** Actualización: límites de mi máquina: ** #getconf ARG_MAX 2097152 #ulimit -a tamaño del archivo principal (bloques, -c) 0 tamaño de segmento de datos (kbytes, -d) ilimitado prioridad de programación (-e) 0 tamaño de archivo (bloques, -f) ilimitado señales pendientes (-i) 256634 memoria máxima bloqueada (kbytes, -l) 64 tamaño máximo de memoria (kbytes, -m) ilimitado abrir archivos (-n) 1024 tamaño de la tubería (512 bytes, -p) 8 Colas de mensajes POSIX (bytes, -q) 819200 prioridad en tiempo real (-r) 0 tamaño de pila (kbytes, -s) 8192 tiempo de la CPU (segundos, -t) ilimitado Max procesos de usuario (-u) 4096 memoria virtual (kbytes, -v) ilimitada bloqueos de archivos (-x) ilimitados
Respuestas
En la mayoría de los sistemas, el kernel limita el tamaño de los argumentos a la execve()llamada al sistema (args de línea de comando + variables de entorno). En Linux, el límite está relacionado con el tamaño máximo de pila, aunque normalmente obtendría al menos 2 MB en total para el límite de tamaño de pila predeterminado de 8 MB. También limita un único argumento a 128 kB, consulte, por ejemplo, ¿hay un máximo para la expansión del nombre de archivo bash (globbing) y, si es así, cuál es? y aumentar el límite de 128 KB en variables de entorno en Linux
Si PHP se ejecuta sh -c 'command line'cuando llama, exec("command line")entonces el argumento de -cpodría exceder ese límite de 128 kB. El hecho de que la línea de comandos se divida posteriormente en palabras distintas por el shell no ayudaría.
Cuando tiene tantos argumentos, desea pasarlos a GNU Parallel a través de la entrada estándar (stdin) o mediante archivos.
Haría algo como (no probado):
$f = popen("parallel","w"); fwrite($f,$commands); close ($f);
De esta forma, es posible que pueda evitar el archivo temporal.
Entonces, con toda su ayuda, aquí está mi solución: 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 ) );
INTENTO:
#!/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
También puede ejecutar su opción de paralelo con -Dall para tener más contexto de lo que está sucediendo, logré escanear casi 40.000 hosts en 7 h. El servidor web agregó todos los objetivos al archivo en segundos y, cuando mi ejecutivo inicia un proceso en segundo plano, no tiene que esperar el resultado (lo enviamos al archivo).
Y el script check.sh también actualiza el registro de la base de datos Mariadb para un objetivo en particular a medida que avanza.