인수는 php exec ()를 bash 스크립트로 제한합니다.
PHP에서 bash 스크립트로 50000 개의 인수를 전달하는 데 얼마나 오래 걸리는지 테스트 한 결과, 내가 할 수없는 한 한 번에 PHP에서 bash 스크립트로 1000 개의 인수도 전달할 수없는 것으로 나타났습니다 .
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
그래서 내 PHP 는 bash에 인수를 전달 하고 bash는 오류와 함께 outputFile에 인쇄 합니다. pidfile 은이 exec로 시작된 프로세스의 pid를 보유합니다. 실행 된 프로세스가 없기 때문에 명령이 실행되지 않습니다. exec에서 전달 된 인수에 대한 제한이 있습니까? 또는 PHP 또는 Linux 쉘에서? 저는 php 5.4와 Linux Redhat 7 을 실행하고 있습니다. GNU 병렬을 사용하여 프로세스를 실행하고 싶지만 PHP가 단일 스레드이기 때문에 (이를 전달할 라이브러리가 있지만 피하는 것이 좋습니다). 어떻게 든 텍스트 파일에 전달하고이 텍스트 파일에서 가져 오는 스크립트에 exec를 전달할 수 있습니까? 도움!
** 업데이트 : 내 컴퓨터 제한 : ** #getconf ARG_MAX 2097152 #ulimit -a 코어 파일 크기 (블록, -c) 0 데이터 세그먼트 크기 (KB, -d) 무제한 스케줄링 우선 순위 (-e) 0 파일 크기 (블록, -f) 무제한 보류중인 신호 (-i) 256634 최대 잠긴 메모리 (KB, -l) 64 최대 메모리 크기 (KB, -m) 무제한 열린 파일 (-n) 1024 파이프 크기 (512 바이트, -p) 8 POSIX 메시지 큐 (바이트, -q) 819200 실시간 우선 순위 (-r) 0 스택 크기 (KB, -s) 8192 CPU 시간 (초, -t) 무제한 최대 사용자 프로세스 (-u) 4096 가상 메모리 (KB, -v) 무제한 파일 잠금 (-x) 무제한
답변
대부분의 시스템에서 커널은 execve()
syscall 에 대한 인수 크기를 제한합니다 (명령 줄 args + 환경 변수). Linux에서 제한은 최대 스택 크기와 관련이 있지만 일반적으로 기본 스택 크기 제한 인 8MB에 대해 총 2MB 이상을 얻습니다. 또한 단일 인수를 128kB로 제한합니다. 예를 들어 bash 파일 이름 확장 (globbing)에 최대 값이 있습니까? 그렇다면 무엇입니까? 및 Linux에서 환경 변수에 대한 128KiB 제한 올리기
sh -c 'command line'
호출 할 때 PHP가 실행 되면 exec("command line")
인수 -c
가 128KB 제한을 초과 할 수 있습니다. 명령 줄이 나중에 쉘에 의해 별개의 단어로 분할된다는 사실은 도움이되지 않습니다.
이렇게 많은 인수가있는 경우 표준 입력 (stdin) 또는 파일을 통해 GNU Parallel에 전달하려고합니다.
나는 다음과 같은 일을 할 것입니다.
$f = popen("parallel","w"); fwrite($f,$commands); close ($f);
이렇게하면 임시 파일을 피할 수 있습니다.
여기에 모든 도움이 필요하면 내 솔루션이 있습니다. 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 ) );
세게 때리다:
#!/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
-Dall 옵션을 사용하여 병렬로 실행하여 더 많은 상황을 파악할 수도 있습니다. 저는 7 시간 동안 거의 40.000 개의 호스트를 스캔 할 수있었습니다. 웹 서버는 몇 초 만에 모든 대상을 파일에 추가했으며 내 exec가 시작될 때 사용 된 백그라운드 프로세스가 결과를 기다릴 필요가 없습니다 (파일로 출력 중입니다).
또한 check.sh 스크립트는 특정 대상에 대한 Mariadb 데이터베이스 레코드를 업데이트합니다.