매개변수는 php exec()를 bash 스크립트로 제한합니다.

매개변수는 php exec()를 bash 스크립트로 제한합니다.

50000개의 매개변수를 PHP에서 bash 스크립트로 전달하는 데 걸리는 시간을 테스트해 보세요. 결과는 다음과 같습니다.가능하지 않으면 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는 다음으로 인쇄합니다.결과물 파일그리고 어떤 오류.pid 파일이 exec로 시작된 프로세스의 pid가 저장됩니다. 프로세스가 시작되지 않으므로 명령이 실행되지도 않습니다.exec에 전달되는 매개변수에 제한이 있나요? 아니면 PHP나 Linux 쉘에서? 저는 PHP 5.4와 Linux Redhat 7을 실행하고 있습니다. 나는 GNU를 사용하여 프로세스를 병렬로 실행하고 싶지만 PHP는 단일 스레드이기 때문에 (이를 제공하는 라이브러리가 있지만 나는 그것을 피하고 싶습니다). 어쩌면 어떻게든 그것을 텍스트 파일에 전달하고 해당 텍스트 파일에서 추출된 스크립트를 실행할 수 있을까요? 돕다!

**업데이트: 내 컴퓨터 제한 사항:**
#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
스택 크기(킬로바이트, -s) 8192
CPU 시간(초, -t) 무제한
최대 사용자 프로세스 수(-u) 4096
가상 메모리(킬로바이트, -v) 무제한
파일 잠금(-x) 무제한

답변1

대부분의 시스템에서 커널은 execve()시스템 호출 인수(명령줄 인수 + 환경 변수)의 크기를 제한합니다. Linux에서 제한은 최대 스택 크기와 관련이 있지만 일반적으로 기본 스택 크기 제한이 8MB이면 총 크기가 최소 2MB가 됩니다. 또한하나의매개변수는 128kB입니다.Bash 파일 이름 확장(와일드카드)에 최대 제한이 있습니까? 그렇다면 무엇입니까?그리고Linux의 환경 변수 제한이 128KiB 증가했습니다.

sh -c 'command line'PHP를 호출할 때 PHP가 실행 중이라면 exec("command line")매개변수가 -c128kB 제한을 초과할 가능성이 높습니다. 명령줄이 쉘에 의해 다른 단어로 분할된다는 사실은 도움이 되지 않습니다.

답변2

인수가 너무 많으면 표준 입력(stdin)이나 파일을 통해 인수를 GNU Parallel에 전달하려고 합니다.

나는 (테스트되지 않은) 다음과 같은 작업을 수행할 것입니다.

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

이렇게 하면 임시 파일을 피할 수 있습니다.

답변3

그래서 여러분의 도움으로 제 해결책은 다음과 같습니다: 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 데이터베이스 레코드도 업데이트합니다.

관련 정보