Executar um script / aplicativo remoto no modo desanexado no Ansible

6

Estou tendo problemas para executar um script de inicialização de aplicativo remoto "separadamente" de um guia Ansible. O script será executado, mas não consigo obtê-lo / ficar desanexado. Eu provavelmente estou fazendo algo errado, mas o que?

Aqui está meu reprodutor.

  1. Meu aplicativo Java remoto no Test.java é executado por 10 segundos:

    class Test {
        public static void main(String[] args) {
            for (int I = 1; I <= 10; i++) {
                System.out.println("Hello world " + I);
    
                try { Thread.sleep(1000);
                } catch (Exception e) { System.out.println("Exception caught: " + e);
                }
    } } }
    

Compilar isso para Test.class (javac Test.java), então executar essa classe com "java Test" funciona como esperado (fornece 10 mensagens de saída e depois sai).

  1. Meu script de shell executável (como no chmod 755) executando este aplicativo é o seguinte:

    #!/bin/bash
    java Test &
    

Executar isso manualmente também é perfeitamente correto: o aplicativo Java é executado e gera a mesma saída padrão no meu console, mas o shell script saiu e estou de volta ao controle da minha sessão bash.

  1. Agora, execute-o em um playbook ansible em outro servidor. Eu tentei usar o módulo "comando" e o módulo "shell" de maneiras diferentes, mas sem sucesso ...

    ---
    - hosts: vagrant1
      gather_facts: false
    
      tasks:
      - debug: msg="Running test app through Ansible shell module..."
    
      - name: Start application
        shell: "/tmp/test.sh"
        args:
          chdir: "/tmp"
          executable: "/bin/bash"
    
      - debug: msg="Running test app through Ansible command module..."
    
      - name: Start application
        command: "nohup /tmp/test.sh &"
        args:
          chdir: "/tmp"
    

Tudo isso corre muito bem, ou seja, o script de shell é executado, o aplicativo Java é executado e faz o seu trabalho (ou seja, é executado por 10 segundos, gera saída e sai). Mas o ansible-playbook é executado até que o aplicativo Java termine e, em seguida, retorna a saída que o aplicativo Java gerou. Por que não desanexará o script de shell e terminará o manual?

A saída ansible-playbook é:

    monsterkill@monsterkill-ub-dt:~/playbooks$ ansible-playbook testrun.yaml -v

    PLAY [vagrant1] *************************************************************** 

    TASK: [debug msg="Running test app through Ansible shell module..."] ********** 
    ok: [vagrant1] => {
        "msg": "Running test app through Ansible shell module..."
    }

    TASK: [Start application] ***************************************************** 
    changed: [vagrant1] => {"changed": true, "cmd": " /tmp/test.sh ", "delta": "0:00:10.052927", "end": "2015-01-29 00:14:43.327418", "rc": 0, "start": "2015-01-29 00:14:33.274491", "stderr": "", "stdout": "Hello world 1\nHello world 2\nHello world 3\nHello world 4\nHello world 5\nHello world 6\nHello world 7\nHello world 8\nHello world 9\nHello world 10"}

    TASK: [debug msg="Running test app through Ansible command module..."] ******** 
    ok: [vagrant1] => {
        "msg": "Running test app through Ansible command module..."
    }

    TASK: [Start application] ***************************************************** 
    changed: [vagrant1] => {"changed": true, "cmd": ["nohup", "/tmp/test.sh", "&"], "delta": "0:00:10.045643", "end": "2015-01-29 00:14:53.557164", "rc": 0, "start": "2015-01-29 00:14:43.511521", "stderr": "nohup: ignoring input", "stdout": "Hello world 1\nHello world 2\nHello world 3\nHello world 4\nHello world 5\nHello world 6\nHello world 7\nHello world 8\nHello world 9\nHello world 10"}

    PLAY RECAP ******************************************************************** 
    vagrant1                   : ok=4    changed=2    unreachable=0    failed=0
    
por SadBunny 29.01.2015 / 01:31

3 respostas

13

Basta usar uma ação assíncrona com poll: 0 :

- command: yourscript.sh
  async: 45
  poll: 0

Essas opções são necessárias para evitar que o ansible mate os processos filhos dessa tarefa com os.killpg .

Em seguida, em yourscript.sh:

java Test &
disown

rejeitado remove o processo da tabela de trabalhos, portanto, o SIGHUP não é enviado para ele. nohup faz o mesmo, mas não é necessário.

Editar : Observe que a rejeição não está disponível em todos os shells (por exemplo, dash)

    
por 28.05.2015 / 10:38
5

Os servidores do google devem estar fumando agora, mas encontrei uma solução. Quando percebi que o Ansible executa todos os seus comandos remotos através de chamadas ssh separadas, eu testei fazendo isso manualmente a partir do servidor ansible e descobri que isso tem a ver com a funcionalidade ssh.

A resposta é, aparentemente, ter o script que eu chamei para fazer o truque de fundo duplo, combinado com um nohup para fazer com que ele ignore os sinais de interrupção (SIGHUP) e combinado com a desconexão dos fluxos stdout e stderr. Então, o script de inicialização remota não faz mais:

java Test &

... mas agora:

( ( nohup java Test 1>/dev/null 2>&1 ) & )

que faz o que eu quero. O ansible-playbook agora ativa o script remoto que, por sua vez, ativa o aplicativo java, mas, em seguida, faz o backup duplo e o nohups e desconecta os fluxos de saída.

Esse thread stackoverflow me ajudou.

    
por 29.01.2015 / 05:23
5

A execução do seu script como Daemon com o daemon start-stop parece ser uma solução mais elegante aqui. link

- name: Start application
  shell: "start-stop-daemon --start --quiet --pidfile /var/run/test --exec /tmp/test.sh"
  args:
    executable: "/bin/bash"
    
por 23.08.2015 / 16:04