los argumentos limitan php exec () al script bash

Dec 02 2020

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

2 ilkkachu Dec 02 2020 at 01:28

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.

1 OleTange Dec 02 2020 at 15:41

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.

dwt.bar Dec 02 2020 at 23:48

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.