킥스타트 중에 쉘 스크립트를 백그라운드에 어떻게 넣을 수 있습니까?

킥스타트 중에 쉘 스크립트를 백그라운드에 어떻게 넣을 수 있습니까?

상태 서버에 POST 요청을 하여 주요 사항에 대한 진행 상황을 보고하는 Red Hat Kickstart 프로세스가 있습니다.

%pre도중에는 괜찮지 %post만 실제 빌드가 발생하면 정보 블랙홀이 됩니다.

진행 상황에 대한 대략적인 아이디어를 제공하기 위해 설치된 패키지 수를 보고하는 간단한 셸 조각을 작성했습니다. 나는 다음을 넣었습니다 %pre.

%pre

## various other stuff here, all works fine ##

cat > /tmp/rpm_watcher.sh << EOF_RPM
PREV=-1
while true
do
    COUNT="\$(rpm -qa | wc -l)"
    if [ \${COUNT} -ne \${PREV} ] ; then
        /bin/wget --post-data " ${Hostname} : Package count \${COUNT}" ${builddest}/log
        PREV=\${COUNT}
    fi
    sleep 15
done
EOF_RPM
/bin/sh /tmp/rpm_watcher.sh &
disown -a
%end

그러나 위에서 백그라운드 작업으로 시작하면 %pre스크립트가 완료될 때까지 기다리지 않고 %pre완료되지 않습니다(생성된 스크립트를 종료하면 %pre완료되고 빌드가 올바르게 시작됩니다).

사전 설치된 환경에서는 사용할 수 없기 때문에 사용할 수 없습니다. nohup및 를 사용하는 경우에도 마찬가지입니다.at nowscreen

을(를) 사용해 보았는데 disown -a사용 가능합니다. 프로세스를 성공적으로 거부한 것 같지만(PID 1에 속함) 여전히 스크립트가 완료될 때까지 멈춥니다.

누구든지 나에게 대안을 제공할 수 있습니까?

답변1

당신은 해결책에 매우 가깝습니다. Anaconda(설치 프로그램)는 Python으로 작성되었으므로 코드를 자세히 살펴보았습니다.

궁극적으로 다음과 같은 스크립트를 실행합니다.

    rc = iutil.execWithRedirect(self.interp, ["/tmp/%s" % os.path.basename(path)],
                                stdin = messages, stdout = messages, stderr = messages,
                                root = scriptRoot)

더 자세히 살펴보면 "iutil.py"에 정의된 iutil.execWithRedirect를 찾을 수 있습니다. 이 함수는 궁극적으로 subprocess.Popen(Python 내장)을 사용하여 명령을 실행합니다. %pre 스크립트에서 STDOUT 및 STDERR의 내용을 가져오는 것도 매우 어렵습니다.

코드는 다음과 같습니다.

    #prepare tee proceses
    proc_std = tee(pstdout, stdout, program_log.info, command)
    proc_err = tee(perrout, stderr, program_log.error, command)

    #start monitoring the outputs
    proc_std.start()
    proc_err.start()

    proc = subprocess.Popen([command] + argv, stdin=stdin,
                            stdout=pstdin,
                            stderr=perrin,
                            preexec_fn=chroot, cwd=root,
                            env=env)

    proc.wait()
    ret = proc.returncode

    #close the input ends of pipes so we get EOF in the tee processes
    os.close(pstdin)
    os.close(perrin)

    #wait for the output to be written and destroy them
    proc_std.join()
    del proc_std

    proc_err.join()
    del proc_err

따라서 현재 가지고 있는 것을 사용하면 백그라운드로 분기하여 proc.wait() 및 os.close 호출을 우회할 수 있습니다.

proc_std 및 proc_err은 반복적으로 호출되는 스레드입니다.독서선STDOUT 및 STDERR에서. EOF를 만날 때까지 계속해서 읽습니다. 스크립트는 %pre 스크립트에서 STDOUT 및 STDERR 소켓을 상속하므로 EOF가 발생하지 않습니다. 그런 다음 Anaconda는 중단되고 STDOUT을 읽는 스레드가 종료될 때까지 기다리지만("proc_std.join()" 라인에서) 이런 일은 결코 발생하지 않습니다.

이것은 매우 혼란스러운 문제이지만 궁극적으로 매우 간단한 해결책입니다. 바꾸다:

/bin/sh /tmp/rpm_watcher.sh &

사용

/bin/sh /tmp/rpm_watcher.sh > /dev/null 2>&1 < /dev/null &

이렇게 하면 스크립트가 STDOUT 및 STDERR을 상속하지 않으므로 Anaconda가 중단되지 않고 설치를 계속할 수 있습니다.

답변2

다음과 같이 스크립트를 배경으로 두는 대신 스크립트의 while 루프를 배경으로 설정하는 경우:

while true
do
    COUNT="\$(rpm -qa | wc -l)"
    if [ \${COUNT} -ne \${PREV} ] ; then
        /bin/wget --post-data " ${Hostname} : Package count \${COUNT}" ${builddest}/log
        PREV=\${COUNT}
    fi
    sleep 15
done &

done루프 라인 끝에 "&" 기호를 추가했습니다 while.

인용하다

답변3

아마도 Anaconda의 구현은 제안된 솔루션을 깨기 위해 발전했을 것입니다. 나는 이 과정을 결코 부정할 수 없다.

이제 Anaconda 환경에서 사용할 수 있습니다 systemd. 이는 저에게 효과적이었습니다(적응 문제).

cat > /etc/systemd/system/rpm-watcher.service << EOF
[Service]
Type=simple
ExecStart=/bin/sh /tmp/rpm_watcher.sh
EOF

systemctl daemon-reload
systemctl start rpm-watcher

답변4

글쎄, 가끔 at now" "로 시작하는 게 나한테는 괜찮을 때도 있어

이제 즉시 반환되며 시작된 프로세스는 백그라운드에서 실행됩니다.

atd당연히 달려야죠 :)

예를 들어

/bin/echo "/custom/scripte/test.sh" | /usr/bin/at now

관련 정보