argumentos limitam php exec () a script bash
Testar quanto tempo levará para passar 50000 argumentos de php para um script bash, acontece que não posso passar nem mesmo 1000 argumentos de php para um script bash de uma vez, a menos que eu possa?
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
Então meu php passa argumentos para o bash , o bash imprime para outputFile junto com quaisquer erros. pidfile conterá o pid do processo que foi lançado com este exec. O comando nem está sendo executado porque não vejo nenhum processo iniciado. Existe algum limite para argumentos passados em exec? ou do PHP ou no shell do Linux? Estou executando o php 5.4 e Linux Redhat 7 , quero executar processos usando GNU paralelo, mas porque o PHP é single-threaded (existem bibliotecas para passar isso, mas eu preferiria evitar isso). Talvez eu pudesse passá-lo de alguma forma para um arquivo de texto e exec para um script que puxa desse arquivo de texto? Socorro!
** Atualização: meus limites de máquina: ** #getconf ARG_MAX 2097152 #ulimit -a tamanho do arquivo principal (blocos, -c) 0 tamanho do segmento de dados (kbytes, -d) ilimitado prioridade de agendamento (-e) 0 tamanho do arquivo (blocos, -f) ilimitado sinais pendentes (-i) 256634 memória máxima bloqueada (kbytes, -l) 64 tamanho máximo da memória (kbytes, -m) ilimitado abrir arquivos (-n) 1024 tamanho do tubo (512 bytes, -p) 8 Filas de mensagens POSIX (bytes, -q) 819200 prioridade em tempo real (-r) 0 tamanho da pilha (kbytes, -s) 8192 tempo de CPU (segundos, -t) ilimitado processos máximos do usuário (-u) 4096 memória virtual (kbytes, -v) ilimitada bloqueios de arquivo (-x) ilimitado
Respostas
Na maioria dos sistemas, o kernel limita o tamanho dos argumentos ao execve()
syscall (args de linha de comando + vars de ambiente). No Linux, o limite está relacionado ao tamanho máximo da pilha, embora normalmente você obtenha pelo menos 2 MB no total para o limite de tamanho de pilha padrão de 8 MB. Também limita um único argumento a 128 kB, consulte, por exemplo, há um máximo para a expansão do nome do arquivo bash (globbing) e, se sim, qual é? e aumentar o limite de 128 KiB em variáveis de ambiente no Linux
Se o PHP for executado sh -c 'command line'
quando você chamar exec("command line")
, o argumento para -c
pode exceder o limite de 128 kB. O fato de a linha de comando ser posteriormente dividida em palavras distintas pelo shell não ajudaria.
Quando você tem tantos argumentos, você deseja passá-los para o GNU Parallel via entrada padrão (stdin) ou via arquivos.
Eu faria algo como (não testado):
$f = popen("parallel","w"); fwrite($f,$commands); close ($f);
Dessa forma, você pode evitar o arquivo temporário.
Então, com toda a sua ajuda, aqui está minha solução: 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
Você também pode rodar seu paralelo com a opção -Dall para ter mais contexto do que está acontecendo, consegui escanear quase 40.000 hosts em 7h. O servidor Web adicionou todos os destinos ao arquivo em segundos e, conforme meu exec inicia, um processo em segundo plano usado não precisa esperar pelo resultado (estamos enviando para o arquivo).
E o script check.sh também está atualizando o registro do banco de dados Mariadb para um destino específico à medida que avança.