argumenty ograniczają php exec () do skryptu bash

Dec 02 2020

Testowanie, jak długo zajmie przekazanie 50000 argumentów z php do skryptu bash, okazuje się, że nie mogę jednocześnie przekazać nawet 1000 argumentów z php do skryptu bash, chyba że mogę?

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

Więc mój php przekazuje argumenty do bash , bash drukuje do outputFile wraz z wszelkimi błędami. pidfile będzie zawierał pid procesu, który został uruchomiony tym exec. Polecenie nie jest nawet wykonywane, ponieważ nie widzę uruchomionego żadnego procesu. Czy istnieje limit przekazywanych argumentów w exec? lub z PHP lub w powłoce Linuksa? Używam php 5.4 i Linux Redhat 7 Chcę uruchamiać procesy równolegle z GNU, ale ponieważ PHP jest jednowątkowe (są biblioteki, które to przekazują, ale wolałbym tego uniknąć). Może mógłbym jakoś przekazać to do pliku tekstowego i wykonać do skryptu, który pobiera z tego pliku tekstowego? Wsparcie!

** Aktualizacja: moje limity maszyn: **
#getconf ARG_MAX
2097152
 
#ulimit -a
rozmiar pliku podstawowego (bloki, -c) 0
rozmiar seg. danych (kilobajty, -d) nieograniczony
priorytet planowania (-e) 0
rozmiar pliku (bloki, -f) nieograniczony
sygnały oczekujące (-i) 256634
max zablokowana pamięć (kilobajty, -l) 64
maksymalny rozmiar pamięci (kilobajty, -m) nieograniczony
otwarte pliki (-n) 1024
rozmiar potoku (512 bajtów, -p) 8
Kolejki komunikatów POSIX (bajty, -q) 819200
priorytet czasu rzeczywistego (-r) 0
rozmiar stosu (kilobajty, -s) 8192
czas procesora (sekundy, -t) nieograniczony
max procesów użytkownika (-u) 4096
pamięć wirtualna (kilobajty, -v) nieograniczona
blokady plików (-x) nieograniczone

Odpowiedzi

2 ilkkachu Dec 02 2020 at 01:28

W większości systemów jądro ogranicza rozmiar argumentów do wywołania execve()systemowego (argumenty wiersza poleceń + zmienne środowiskowe). W systemie Linux limit ten jest powiązany z maksymalnym rozmiarem stosu, chociaż zwykle otrzymujesz co najmniej 2 MB łącznie dla domyślnego limitu rozmiaru stosu wynoszącego 8 MB. Ogranicza również pojedynczy argument do 128 kB, zobacz np. Czy istnieje maksimum rozszerzenia nazwy pliku bash (globowanie), a jeśli tak, to co to jest? i Zwiększ limit 128 KB na zmienne środowiskowe w systemie Linux

Jeśli PHP działa, sh -c 'command line'gdy wywołujesz, exec("command line")argument do -cmoże przekroczyć ten limit 128 kB. Fakt, że wiersz poleceń zostanie następnie podzielony na odrębne słowa przez powłokę, nie pomoże.

1 OleTange Dec 02 2020 at 15:41

Kiedy masz tyle argumentów, chcesz przekazać je do GNU Parallel przez standardowe wejście (stdin) lub przez pliki.

Zrobiłbym coś takiego (niesprawdzone):

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

W ten sposób możesz uniknąć pliku tymczasowego.

dwt.bar Dec 02 2020 at 23:48

Więc z całą twoją pomocą jest moje rozwiązanie: 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 ) );

GRZMOTNĄĆ:

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

Możesz także uruchomić swoją równoległość z opcją -Dall, aby mieć więcej kontekstu, co się dzieje, udało mi się przeskanować prawie 40 000 hostów w 7 godzin. Serwer WWW dodał wszystkie cele do pliku w ciągu kilku sekund, a ponieważ mój exec uruchamia proces w tle, nie musi czekać na wynik (wysyłamy go do pliku).

A skrypt check.sh aktualizuje również rekord bazy danych Mariadb dla określonego celu na bieżąco.