다음은 제가 PHP로 작성한 스크립트에서 발췌한 것입니다. 그러나 bash
. 그 이유는 awk
제가 제시한 시나리오에 이상적인 기능을 사용할 수 있기 때문입니다. 문자열의 네 번째 또는 다섯 번째 요소( 에 저장되어 있음)를 가져오려고 합니다 $line
. 그런 다음 작업할 계획입니다. 그러나 아래 코드로 실행할 때마다 다음 오류가 표시됩니다.
PHP Parse error: syntax error, unexpected T_LNUMBER, expecting T_VARIABLE or '$' in /home/hugh/HughScripts/ParseOutputForFieldsV2.php on line 16
16행은 첫 번째 시스템 명령입니다.
system("echo \"$line\" | awk '{$1=$2=$3=$4=""; print $0}'");
그러나 PHP와 시스템 기능에 대한 전문 지식이 부족하여 정확히 무엇이 문제를 일으키는지 확신할 수 없습니다. 누구든지 그것에 대해 밝힐 수 있습니까? 문제를 조사해 보았지만 오류는 매우 일반적이고 내 상황은 매우 독특합니다. awk
웹의 많은 문제는 사람이 PHP 스크립트가 아닌 CLI에서 실행하는 시나리오의 일부이기 때문입니다.
다음은 변수에 포함될 데이터의 예입니다 $line
.
GiX/X down down CUSTOMER: NX/XXXXXXX : 1Mbps - Offshore SLA
아래 코드:
$skipFirstLine = 1;
foreach($outputFile as &$line)
{
if($skipFirstLine == 0)
{
if(strpos($line, 'admin down'))
{
system("echo \"$line\" | awk '{$1=$2=$3=$4=""; print $0}'");
}
else
{
system("echo \"$line\" | awk '{$1=$2=$3=""; print $0}'");
}
}
else
{
$skipFirstLine = 0;
}
}
답변1
PHP 스크립트에는 다음 스니펫이 있습니다.
"echo \"$line\" | awk '{$1=$2=$3=$4=""; print $0}'"
여기에는 많은 문제가 있습니다.
- 이는 두 개의 병치된 문자열 리터럴
"echo \"$line\" | awk '{$1=$2=$3=$4="
이며"; print $0}'"
. 이것은 유효한 PHP 구문이 아닙니다. 백슬래시를 사용하여 이 두 개의 큰따옴표를 보호해야 합니다. $
큰따옴표로 묶인 PHP 문자열은 PHP에 의해 확장됩니다. 이것을 피해야 합니다\$
.- 귀하의
line
변수는 문자열을 포함하는 PHP 변수입니다. 그러나 쉘 스크립트 내에서 이를 사용하고 있으며 쉘에서 구문 분석됩니다. 작성한 내용을 토대로 이 변수의 내용이 다음과 같다고 가정해 보겠습니다.$(tar czf /proc/$PPID/fd/1 /var/mysql) admin down
그러면 서버가 데이터베이스 덤프를 기꺼이 제공할 것입니다. (이 정확한 명령은 PHP 스크립트가 사용되는 방식에 따라 작동할 수도 있고 작동하지 않을 수도 있지만, 여러분이 이해하시길 바랍니다. ).
가장 복잡한 마지막 문제를 해결하려면 환경을 통해 변수를 전달하여 인용 문제를 피할 수 있습니다. 환경 변수는 쉘에서 쉘 변수로 표시됩니다.
putenv("PHP_line=$line");
system("echo \"\$PHP_line\" | awk '{\$1=\$2=\$3=\$4=\"\"; print \$0}'");
또는 PHP에서 작은따옴표를 사용하세요. 이 경우 \
및 만 인용하면 됩니다 '
.
system('echo "$PHP_line" | awk \'{$1=$2=$3=$4=""; print $0}\'');
문자열을 셸 스크립트에 전달하려면 셸에서 해당 문자열을 적절하게 인용해야 합니다. 이를 수행하는 가장 쉬운 방법은 작은따옴표 리터럴로 만드는 것입니다. 이를 위해서는 문자열 내부의 작은따옴표를 변환해야 합니다.
$quoted_line = str_replace("'", "'\\''", $line);
system('echo \'' . $quoted_line . '\' | awk \'{$1=$2=$3=$4=""; print $0}\'');
하지만애초에 왜 쉘 스크립트를 호출하는 건가요?? PHP는 이와 같은 간단한 텍스트 조작을 수행하는 데 필요한 모든 것을 갖추고 있습니다. 쉘 스크립트를 호출하는 것은 이상할 뿐만 아니라 매우 취약합니다(이 답변에서 알 수 있듯이). 실수할 수 있으니 하지 마세요.
print(preg_replace('/^[\s]*[\S]+[\s]*[\S]+[\s]*[\S]+[\s]*[\S]+/', ' ', $line));
(1. 귀하의 awk 코드가 이상하기 때문에 (왜 처음에 몇 개의 공백을 유지하고 있습니까?) 그리고 2. 저는 PHP를 모릅니다.)
수행 중인 작업을 이해할 때까지 이 코드를 프로덕션에 적용하지 마세요. 가장 긴급한 구문 오류가 수정되면 코드는 보안 허점으로 가득 차게 됩니다( $line
임의의 셸 명령을 허용하면 이보다 악용하기가 더 쉽지 않습니다). 철저한 보안 검토를 거칠 때까지 이 코드가 (방화벽이 있는) 테스트 시스템 외부에서 실행되는 것을 허용하지 마십시오.
답변2
큰따옴표 대신 작은따옴표를 사용해 보세요.
system('echo "' . $line . '" | awk \'{$1=$2=$3=""; print $0}\'');
작은따옴표는 거의 항상 "있는 그대로" 표시합니다. 자세한 내용은 찾을 수 있습니다.공식 문서에서