gli argomenti limitano php exec () allo script bash

Dec 02 2020

Testando quanto tempo ci vorrà per passare 50000 argomenti da php a uno script bash, si scopre che non posso passare nemmeno 1000 argomenti da php a uno script bash contemporaneamente, a meno che non sia possibile?

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

Quindi il mio php passa gli argomenti alla bash , bash stampa al file output insieme a qualsiasi errore. pidfile conterrà il pid del processo avviato con questo exec. Il comando non viene nemmeno eseguito perché non vedo alcun processo avviato. C'è un limite per gli argomenti passati in exec? o da PHP o nella shell di Linux? Sto eseguendo php 5.4 e Linux Redhat 7 Voglio eseguire processi usando GNU parallel ma poiché PHP è single-threaded (ci sono librerie per passare questo ma preferirei evitarlo). Forse potrei passarlo in qualche modo a un file di testo ed eseguire uno script che estrae da questo file di testo? Aiuto!

** Aggiornamento: limiti della mia macchina: **
#getconf ARG_MAX
2097152
 
#ulimit -a
dimensione del file core (blocchi, -c) 0
dimensione seg dati (kbyte, -d) illimitata
priorità di pianificazione (-e) 0
dimensione del file (blocchi, -f) illimitata
segnali in sospeso (-i) 256634
memoria massima bloccata (kbyte, -l) 64
dimensione massima della memoria (kbyte, -m) illimitata
apri file (-n) 1024
dimensione pipe (512 byte, -p) 8
Code di messaggi POSIX (byte, -q) 819200
priorità in tempo reale (-r) 0
dimensione dello stack (kbyte, -s) 8192
tempo della CPU (secondi, -t) illimitato
max processi utente (-u) 4096
memoria virtuale (kbyte, -v) illimitata
file lock (-x) illimitati

Risposte

2 ilkkachu Dec 02 2020 at 01:28

Sulla maggior parte dei sistemi, il kernel limita la dimensione degli argomenti alla execve()syscall ( argomenti della riga di comando + variabili di ambiente). Su Linux, il limite è correlato alla dimensione massima dello stack, sebbene in genere si ottengano almeno 2 MB in totale per il limite di dimensione dello stack predefinito di 8 MB. Inoltre limita un singolo argomento a 128 kB, vedere ad es. Esiste un massimo per l'espansione del nome del file bash (globbing) e, in caso affermativo, qual è? e Aumenta il limite di 128 KiB per le variabili di ambiente in Linux

Se PHP viene eseguito sh -c 'command line'quando si chiama, exec("command line")l'argomento a -cpotrebbe superare il limite di 128 kB. Il fatto che la riga di comando venga successivamente suddivisa in parole distinte dalla shell non aiuterebbe.

1 OleTange Dec 02 2020 at 15:41

Quando si hanno così tanti argomenti, è necessario passarli a GNU Parallel tramite lo standard input (stdin) o tramite file.

Vorrei fare qualcosa come (non testato):

$f = popen("parallel","w"); fwrite($f,$commands); close ($f);

In questo modo potresti essere in grado di evitare il file temporaneo.

dwt.bar Dec 02 2020 at 23:48

Quindi con tutto il tuo aiuto ecco la mia soluzione: 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 ) );

BASH:

#!/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

Puoi anche eseguire il tuo parallelo con l'opzione -Dall per avere più contesto su cosa sta succedendo, sono riuscito a scansionare quasi 40.000 host in 7 ore. Il server Web ha aggiunto tutti i target al file in pochi secondi e poiché il mio exec lancia un processo in background utilizzato non deve attendere il risultato (lo stiamo inviando al file).

E lo script check.sh aggiorna anche il record del database Mariadb per un particolare target mentre procede.