CentOS 7 샌드박스에서 파일 설명자를 사용하고 있습니다. 이 작업을 수행하는 동안 흥미로운 상황을 발견했습니다. 간단한 PHP 스크립트가 있다고 가정해 보겠습니다.
$step = 4 * 1024;
echo "php started\n";
while (!\feof(\STDIN)) {
\fwrite(\STDOUT, 'read stdin part: '.\fread(\STDIN, $step)."\n");
}
echo "php finished\n";
bash 스크립트의 하위 프로세스로 백그라운드에서 실행하고 다음과 같은 표준 입력에 전달하고 싶습니다.
php read.php &
phpProcId=$(ps axw -o pid,command | grep 'read' | head -1 | sed -r 's|^\s*([0-9]+)[^0-9]+.*$|\1|g')
echo "phpProcId: $phpProcId"
echo -e "test1\ntest2" >> /proc/$phpProcId/fd/0
그러나 쉘 출력은 다음과 같습니다.
$ sh box.sh
phpProcId: 2818
$ php started
read stdin part:
php finished
Bash 스크립트가 PHP 스크립트 이전에 작업을 완료하고 해당 데이터를 PHP 하위 프로세스에 제때 전달하지 못한 것 같습니다. fd/0에 기록하여 PHP 하위 프로세스에 데이터를 전달하려면 어떻게 해야 합니까? 나는 mkfifo에 대해 알고 있으며 이 경우 의도적으로 사용하고 싶지 않습니다.
답변1
나는 PHP를 전혀 이해하지 못합니다. 이 답변은 쉘에 관한 것입니다.
-
작업 제어 […]가 비활성화된 경우 명시적인 리디렉션이 수행되기 전에 비동기 목록의 표준 입력은 와 동일한 이름을 가진 파일에 할당된 것처럼 처리됩니다
/dev/null
. […](원천)
sh
셸과 같은 스크립트를 실행하면 기본적으로 작업 제어가 비활성화됩니다.이는
php read.php &
일부 fifo에서 읽지 않으며 전체 쉘 스크립트와 stdin을 공유하지도 않음을 의미합니다. 읽고 있는 파일(/proc/…/fd/0
또는 다른 형식) 을 올바르게 식별하더라도 해당 파일에 쓰는 것은/dev/null
fifo에 쓰는 것이 아니라 write 와 같습니다.만약 너라면진짜원하는 것을 인쇄
/proc/…/fd/0
하고 얻으려면 like가 아닌 fifo처럼 동작하는 것을 가리켜야 하므로/dev/null
합리적인mkfifo
기본 선택입니다. 필요하다고 생각한다면 지금 사용하고 있는 이 기기보다 더 좋은 것이
phpProcId
있을 수도 있습니다 . 현재 셸에서 실행된 가장 최근 백그라운드 명령의 10진수 프로세스 ID로 확장됩니다. 하지만 어쩌면 필요하지 않을 수도 있습니다. 왜냐하면...phpProcId=$!
phpProcId=$(ps …)
$!
Bash에서는 프로세스에 인쇄할 파일 설명자를 만들 수 있습니다. 아래 예에서 프로세스는 다음과 같습니다
cat -n
.exec 3> >(cat -n) # ... echo -e "test1\ntest2" >&3 exec 3>&-
이 명명되지 않은 fifo의 쓰기 부분은 우리가 닫힐 때 열리고
exec
설명자는 닫힐 때 열립니다exec 3>&-
(그것 없이: 쉘이 종료될 때). 일부 하위 프로세스가 해당 설명자를 상속하고 열린 상태로 유지하지 않는 한,cat
연결된 후 표준 입력이 더 이상 어떤 것에도 연결되지 않기 때문에 결국 종료됩니다. 그렇지 않더라도echo
우리는cat
그만둘 것이다.cat
스크립트가 종료된 후 인쇄 프롬프트 전후에 대화형 셸의 출력이 표시될 수 있습니다.>(…)
정상적인 형태로 작업할 수 없습니다sh
. 당신이 태그했어요세게 때리다그러나sh box.sh
필요한 경우 사용하십시오bash
(shebang 사용을 고려하십시오)>(…)
.