les arguments limitent php exec () au script bash

Dec 02 2020

Tester combien de temps faudra-t-il pour passer 50000 arguments de php à un script bash, il s'avère que je ne peux même pas passer 1000 arguments de php à un script bash à la fois, à moins que je ne le puisse?

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

Donc mon php passe des arguments au bash , bash imprime au outputFile avec toutes les erreurs. pidfile contiendra le pid du processus qui a été lancé avec cet exécutable. La commande n'est même pas exécutée car je ne vois aucun processus lancé. Y a-t-il une limite pour les arguments passés dans exec? ou de PHP ou dans le shell Linux? J'utilise php 5.4 et Linux Redhat 7 Je veux exécuter des processus en utilisant GNU en parallèle, mais parce que PHP est monothread (il existe des bibliothèques pour transmettre cela mais je préférerais éviter cela). Peut-être que je pourrais le transmettre d'une manière ou d'une autre à un fichier texte et exécuter un script qui extrait de ce fichier texte? Aidez-moi!

** Mise à jour: limites de ma machine: **
#getconf ARG_MAX
2097152
 
#ulimit -a
taille du fichier de base (blocs, -c) 0
taille de segment de données (ko, -d) illimitée
priorité de planification (-e) 0
taille de fichier (blocs, -f) illimitée
signaux en attente (-i) 256634
mémoire verrouillée max. (Ko, -l) 64
taille maximale de la mémoire (Ko, -m) illimitée
fichiers ouverts (-n) 1024
taille du tube (512 octets, -p) 8
Files d'attente de messages POSIX (octets, -q) 819200
priorité en temps réel (-r) 0
taille de la pile (Ko, -s) 8192
temps cpu (secondes, -t) illimité
processus utilisateur max (-u) 4096
mémoire virtuelle (Ko, -v) illimitée
verrous de fichiers (-x) illimités

Réponses

2 ilkkachu Dec 02 2020 at 01:28

Sur la plupart des systèmes, le noyau limite la taille des arguments à l' execve()appel système (ligne de commande args + vars d'environnement). Sous Linux, la limite est liée à la taille maximale de la pile, bien que vous obteniez généralement au moins 2 Mo au total pour la limite de taille de pile par défaut de 8 Mo. Il limite également un seul argument à 128 Ko, voir par exemple Y a-t-il un maximum pour l'expansion des noms de fichiers bash (globbing) et si oui, de quoi s'agit-il? et Augmenter la limite de 128 Ko sur les variables d'environnement sous Linux

Si PHP s'exécute sh -c 'command line'lorsque vous appelez, exec("command line")l'argument to -cpourrait bien dépasser cette limite de 128 Ko. Le fait que la ligne de commande soit ensuite divisée en mots distincts par le shell n'aiderait pas.

1 OleTange Dec 02 2020 at 15:41

Lorsque vous avez autant d'arguments, vous voulez les transmettre à GNU Parallel via une entrée standard (stdin) ou via des fichiers.

Je ferais quelque chose comme (non testé):

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

De cette façon, vous pourrez peut-être éviter le fichier temporaire.

dwt.bar Dec 02 2020 at 23:48

Donc, avec toute votre aide, voici ma solution: 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 ) );

FRAPPER:

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

Vous pouvez également exécuter votre parallèle avec l'option -Dall pour avoir plus de contexte ce qui se passe, j'ai réussi à scanner près de 40.000 hôtes en 7h. Le serveur Web a ajouté toutes les cibles au fichier en quelques secondes et lorsque mon exécuteur lance un processus d'arrière-plan utilisé n'a pas à attendre le résultat (nous le sortons dans le fichier).

Et le script check.sh met également à jour l'enregistrement de la base de données Mariadb pour une cible particulière au fur et à mesure.