Como posso fazer o background de um script de shell durante um Kickstart?

6

Eu tenho um processo Red Hat Kickstart que relata seu progresso em pontos-chave através de uma solicitação POST para um servidor de status.

Isso é bom durante %pre e %post , mas quando a compilação real está ocorrendo entre eles, é um buraco negro informativo.

Eu escrevi um snippet de shell simples que informa sobre o número de pacotes instalados para dar uma idéia aproximada do progresso. Eu coloquei o seguinte em %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

No entanto, quando eu inicio isso como uma tarefa em segundo plano de %pre como acima, ele fica pendurado esperando o script terminar - %pre nunca é concluído (se eu matar o script gerado %pre conclui ea compilação adequada começa).

Eu não posso usar nohup , pois não está disponível no ambiente de pré-instalação, o mesmo vale para usar at now e screen .

Eu tentei usar disown -a , que está disponível; isso parece negar com sucesso o processo (de tal forma que ele é de propriedade do PID 1), mas ainda fica pendurado esperando o script terminar.

Alguém pode me oferecer uma alternativa?

    
por bxm 04.06.2013 / 11:41

3 respostas

3

Você estava muito perto da solução. Anaconda (o instalador) é escrito em Python, então eu fui cavar o código.

Por fim, ele executa o script assim:

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

Um pouco mais de escavação e você pode encontrar o iutil.execWithRedirect definido em 'iutil.py'. Essa função usa subprocess.Popen (um Python interno) para executar o comando. Também tenta muito obter o conteúdo de STDOUT e STDERR do script% pre.

O código é assim:

    #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

Então, com o que você tem, você passa das chamadas proc.wait () e os.close bifurcando-se em segundo plano.

proc_std e proc_err são segmentos que repetidamente chamam readline no STDOUT e STDERR. Eles continuam lendo até que o EOF seja encontrado. Como o script herda o soquete STDOUT e STDERR do script% pre, eles nunca encontrarão EOF. Ananconda então trava esperando o segmento ler STDOUT para sair (na linha 'proc_std.join ()'), o que nunca acontece.

É uma questão muito confusa, mas, no final das contas, uma correção muito simples. Em vez de:

/bin/sh /tmp/rpm_watcher.sh &

use

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

Isso garante que seu script não herde STDOUT e STDERR, então o Anaconda não trava e a instalação pode continuar.

    
por 09.05.2014 / 21:41
1

Em vez de colocar em segundo plano o script, e se você fizer o segundo plano do loop while no script da seguinte forma:

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 &

Observe que eu adicionei o "e" comercial no final da linha done do loop while .

Referências

por 17.06.2013 / 13:26
-1

Hmmm às vezes começando com " at now " faz o trabalho para mim

agora retorna imediatamente - e o processo iniciado é executado em segundo plano ...

atd tem que funcionar, claro:)

por exemplo

/bin/echo "/custom/scripte/test.sh" | /usr/bin/at now
    
por 14.08.2013 / 11:11