argumenty ograniczają php exec () do skryptu bash
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
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 -c
moż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.
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.
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.