Argumente beschränken php exec () auf Bash-Skript

Dec 02 2020

Wenn Sie testen, wie lange es dauern wird, bis 50000 Argumente von PHP an ein Bash-Skript übergeben werden, kann ich nicht einmal 1000 Argumente von PHP gleichzeitig an ein Bash-Skript übergeben, es sei denn, ich kann?

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

Mein PHP übergibt also Argumente an die Bash , Bash druckt zusammen mit etwaigen Fehlern an die Ausgabedatei . pidfile enthält pid des Prozesses, der mit dieser Ausführung gestartet wurde. Der Befehl wird nicht einmal ausgeführt, da kein Prozess gestartet wird. Gibt es eine Grenze für übergebene Argumente in exec? oder von PHP oder in Linux Shell? Ich verwende PHP 5.4 und Linux Redhat 7. Ich möchte Prozesse mit GNU parallel ausführen, aber da PHP Single-Threaded ist (es gibt Bibliotheken, die dies übergeben, aber ich würde es vorziehen, dies zu vermeiden). Vielleicht könnte ich es irgendwie an eine Textdatei übergeben und an ein Skript ausführen, das aus dieser Textdatei abgerufen wird? Hilfe!

** Update: meine Maschinenlimits: **
#getconf ARG_MAX
2097152
 
#ulimit -a
Kerndateigröße (Blöcke, -c) 0
Datenseg-Größe (KB, -d) unbegrenzt
Planungspriorität (-e) 0
Dateigröße (Blöcke, -f) unbegrenzt
anstehende Signale (-i) 256634
Maximal gesperrter Speicher (KB, -l) 64
Maximale Speichergröße (KB, -m) unbegrenzt
Dateien öffnen (-n) 1024
Rohrgröße (512 Bytes, -p) 8
POSIX-Nachrichtenwarteschlangen (Bytes, -q) 819200
Echtzeitpriorität (-r) 0
Stapelgröße (kbytes, -s) 8192
CPU-Zeit (Sekunden, -t) unbegrenzt
max Benutzerprozesse (-u) 4096
virtueller Speicher (kbytes, -v) unbegrenzt
Dateisperren (-x) unbegrenzt

Antworten

2 ilkkachu Dec 02 2020 at 01:28

Auf den meisten Systemen beschränkt der Kernel die Größe der Argumente auf den execve()Systemaufruf (Befehlszeilenargumente + Umgebungsvariablen). Unter Linux bezieht sich das Limit auf die maximale Stapelgröße, obwohl Sie normalerweise mindestens 2 MB für das Standardlimit für die Stapelgröße von 8 MB erhalten. Es beschränkt auch ein einzelnes Argument auf 128 kB, siehe z. B. Gibt es ein Maximum für die Erweiterung des Dateinamens (Globbing) und wenn ja, was ist das? und Erhöhen Sie das 128-KB-Limit für Umgebungsvariablen unter Linux

Wenn PHP sh -c 'command line'beim Aufruf ausgeführt exec("command line")wird, kann das Argument to -cdiese Grenze von 128 kB durchaus überschreiten. Die Tatsache, dass die Befehlszeile anschließend von der Shell in verschiedene Wörter aufgeteilt wird, würde nicht helfen.

1 OleTange Dec 02 2020 at 15:41

Wenn Sie so viele Argumente haben, möchten Sie diese über die Standardeingabe (stdin) oder über Dateien an GNU Parallel übergeben.

Ich würde so etwas wie (ungetestet) machen:

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

Auf diese Weise können Sie möglicherweise die temporäre Datei vermeiden.

dwt.bar Dec 02 2020 at 23:48

Mit all Ihrer Hilfe ist hier meine Lösung: 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

Sie können Ihre Option auch parallel mit -Dall ausführen, um mehr Kontext zu erhalten. Ich habe es geschafft, in 7 Stunden fast 40.000 Hosts zu scannen. Der Webserver fügte der Datei innerhalb von Sekunden alle Ziele hinzu, und wenn mein Exec einen verwendeten Hintergrundprozess startet, muss er nicht auf das Ergebnis warten (wir geben es in die Datei aus).

Das Skript check.sh aktualisiert außerdem den Mariadb-Datenbankdatensatz für ein bestimmtes Ziel.