2010-08-11 2 views
12

프로덕션 서버에서 PHP 5.2.9를 사용하고 있으며 exec() 함수가 "비표준"으로 동작하는 것으로 보입니다.exec는 항상 -1 (또는 127)을 반환합니다.

을 실행하면 $output은 현재 폴더의 파일 목록을 예상대로 포함하지만 $return_var은 예상대로 0 대신 -1로 설정됩니다. 나는 $return_var 명령을 사용하여 명령이 성공적으로 완료되었는지 확인하고 테스트 한 다른 모든 서버에서 예상대로 작동합니다.

누구나 이런 상황에 빠졌습니까?


편집 :

<?php 
$command = "asd"; 

$t1 = time(); 

$output = Array(); 
$result = -5; 
$r = exec($command, $output, $result); 
$t2 = time(); 

echo "<pre>"; 
var_export(Array(
    'command'=>$command, 
    'result'=>$result, 
    'output'=>implode("\n", $output), 
    'r'=>$r, 
    't2-t1'=>$t2-$t1, 
)); 
echo "</pre>"; 

무엇이든 내가 $command에 넣어 명령, $result 항상 심지어 존재하지 않는 명령에 대한 -1이 될 것입니다 ...이

+2

'exec()'가'ls'에 인자를주지 않도록'$ command' 변수가 빈 문자열이라면? 종료 코드가 여전히 '-1'입니까? 그렇다면'ls'의 구현을'man ls'을 사용하여 현재 시스템에 체크인하여 종료 코드'-1'이 정의되어 있는지 확인 했습니까? 다른 명령 (아마'du -h index.html')과도 마찬가지입니까? – sleepynate

+0

'exec ("")'를 호출 할 수없는 것 같습니다. 경고를 인쇄합니다. 다른 명령은 모두 동일하게 작동합니다. 'sleep 5'는 -1로 반환하고, lsmod는 -1 등을 반환합니다 ... – Quamis

+1

제가 볼 수있는 유일한 것은이 [exec php 매뉴얼 페이지에 게시]입니다. (http://www.php.net/manual /en/function.exec.php#76687), 다른 서버에서 작동하고 있기 때문에 이것이 왜 그렇게 될지 명확하지 않습니다. – Troubadour

답변

1

$ 결과 == -1을 반환하는 시스템을 가정은

PHP의 (5.2.9) 간부 인() 함수가 (내가 같은 코드로 윈도우를 작동 할 방법을 모른다) 기반의 유닉스 계열이다 C exec() 프리미티브를 호출하지 않는다. (프로세스를 대체/실행할 수 없다면 -1을 리턴한다. 대신 파이프를 만드는 popen()을 호출하고 fork()를 수행하고 명령으로 셸을 실행합니다. return_value -1은 C 프리미티브의 직접적인 결과가 아니며 명령이 처리 된 방식에 따라 PHP에 의해 내부적으로 작성됩니다. 다른 말로하면, "ls"명령은 잘 실행되었을 수 있습니다. 예를 들어 PHP가 파이프를 제대로 닫을 수 없습니다.

ext/standard/exec.c의 C 코드를 보면 반환 코드가 -1이고 오류로 인해 트리거되는 두 가지 이유가있을 수 있습니다. 두 번째는 popen() 호출 후 발생합니다.

fp = VCWD_POPEN(cmd_p, "r"); 

    if (!fp) { 
     php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to fork [%s]", cmd); 
     goto err; 
    } 
    // ... 
    err: 

    pclose_return = -1; 
    goto done; 

그러나이 경우 결과가 표시되지 않으며 로그에 오류가 표시됩니다.

나중에, RETURN_VALUE가 라인

pclose_return = php_stream_close(stream); 

) (_php_stream_free 살펴보면를 통해 설정됩니다 (php_stream_close()가 _php_stream_free로 대체 매크로입니다()), 반환 할 수있는 가능성이 가장 높은 후보는 -1

입니다
ret = stream->ops->close(stream, preserve_handle ? 0 : 1 TSRMLS_CC); 

간접적으로 C 기본 pclose()를 호출합니다. 설명서에 따라

wait4 (2)가 오류를 반환하거나 다른 오류가 감지되면 pclose() 함수는 -1을 반환합니다.

파이프가 닫히는 동안 오류가 감지되어 결과 데이터를 설정할 수 있습니다.이유를 정확하게 찾으려면 운영 체제 설정 및 로그, PHP 구성 및 컴파일 매개 변수를 확인해야합니다. 내가

  • 는 (해당되는 경우) 최신 버전으로 업데이트 어쩌면 당신의 OS에 대한 패치를 적용하고 추천 할 것입니다

    ,

  • 가 (지금과 같은 최신) 5.3.3 PHP를 업데이트 이후 PHP exec() 코드가 크게 변경되었습니다.

PHP 파일을 실행할 때 기본적으로 보안을 강화하는 PHP suhosin 모듈과 관련된 변경 사항이 버전 5.3에 있음을 알고 있어야합니다.

+0

네, "유닉스와 같았습니다"(정직하게 말하자면, 리눅스 나 유닉스의 맛이라면 나는 이상이 없다). 좋은 답변입니다. 문제는 서버 관리자에 의해 해결되었지만 서버가 무엇을 망가 뜨리거나 수정했는지 알지 못합니다 ... 문제는 서버가 매우 제한적인 방식으로 구성되었다는 것입니다. 아주 작은 명령에 액세스 할 수있었습니다 (예를 들어, SSH를 통해 php-cli를 사용할 수 없었고 다른 명령이 많았습니다.) – Quamis

+0

답변을 가장 완벽하게 받아들이고 서버 관리자가 OS를 적용했다고 가정합니다. – Quamis

0

당신이있어 확인 아주 이상한 safe mode에서 실행되지 않으며 exec가 php.ini의 disable_functions에 나열되어 있지 않습니다.

어느 상황에서든지 exec()이 실패하게되지만, 통지가 제기 될 것이라고 생각합니다.

+0

저는 안전 모드 (안전 모드에서는 exec를 사용할 수 없습니다)에서 실행 중이며 비활성화 된 기능도 없습니다. – Quamis

+0

@Quamis - 귀하의 경우에는 해당되지 않을 것이라고 생각하지만, 안전 모드에서 exec를 사용할 수 있습니다. 그런 다음 안전 모드를 활성화하면 escapeshellcmd()를 사용하여 명령 문자열을 이스케이프 처리합니다. - http://php.net/manual/en/function.exec.php –

0

우리는 strace'ing PHP 프로세스의 결과를 얻을 수 있습니까? 그럴 가능성이 우리가 찾고있는 대답을 포함 할 것입니다.

또한 5.2.14는 5.2 시리즈의 최신 버전입니다. 당신이 거기에서 그것을 시도 할 수있는 어떤 기회? 공유 호스팅 제공 업체의 경우에도 로컬에서 실행되어 동작이 변경되는지 확인할 수 있습니다.

0

두 개의 다른 Linux PC (PHP 5.03 및 PHP 5.2.10)에서 사용해 보았습니다. 둘 다 잘 작동했습니다.

PHP 5.2.10 예 :

array (
    'command' => 'ls', 
    'result' => 0, 
    'output' => 'atmail 
... 
vhosts', 
    'r' => 'vhosts', 
    't2-t1' => 0, 
) 

내가, php.ini 파일의 보안 관련 지침에 대해 다시 한 번 확인하여 검색하려는 디렉토리에 파일 권한을 확인 거라고 및 SELinux 및/또는 AppArmor가 실행 중인지 확인하십시오.

opendir()/readdir()과 같은 별칭을 고려할 수도 있습니다. 문제가 서버 관리자에 의해 고정있어 같은

이럴 .. PSM

0

보인다. 나는 그가 무엇을했는지 모르지만, 이제는 효과가있다. 문제는 서버 관리자가 꽤 "엄격하다"는 것입니다. 어쩌면 그는 약간의 시스템 설정으로 제한을받을 수 있습니다. 예를 들어 SSH 쉘에서 나는 php 바이너리가 설치된 곳을 볼 수 없었다. 나는 SSH 셸이 chrooted되었고 또한 웹 서버 (그 중 하나 또는 완전히 다른 서버이지만 어떤 종류의 마운트를 사용하지 않고도 그 방법이 가능하지 않다는 것을 알았습니다)를 확신합니다 ...

관련 문제