web-dev-qa-db-ja.com

Ansibleでリモートスクリプト/アプリケーションをデタッチモードで実行する

Ansibleプレイブックからリモートアプリケーションの起動スクリプトを「切り離して」実行するのに問題があります。スクリプトは実行されますが、分離したままにすることはできません。私はおそらく何か間違ったことをしていますが、何ですか?

これが私の再生器です。

  1. 私のリモートJavaアプリケーションは10秒間実行されます:

    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);
                }
    } } }
    

これをTest.class(javac Test.Java)にコンパイルしてから、そのクラスを「Java Test」で実行すると、期待どおりに機能します(10の出力メッセージが表示されてから終了します)。

  1. このアプリケーションを実行する実行可能シェルスクリプト(chmod 755など)は次のようになります。

    #!/bin/bash
    Java Test &
    

これを手動で実行することも完全に問題ありません。Javaアプリが実行され、コンソールに同じ標準出力が生成されますが、シェルスクリプトが終了し、bashセッションの制御に戻りました。

  1. 次に、別のサーバーからansibleプレイブックを介して実行します。 「コマンド」モジュールと「シェル」モジュールをさまざまな方法で使用しようとしましたが、役に立ちませんでした...

    ---
    - 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"
    

これはすべて正常に実行されます。つまり、シェルスクリプトが実行されると、Javaアプリケーションが実行され、その機能が実行されます(つまり、10秒間実行され、出力を生成して終了します)。しかし、ansible-playbookは、 Javaアプリケーションが終了し、出力を返しますJavaアプリケーションが生成しました。なぜシェルスクリプトを切り離してプレイブックを終了しないのですか?

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
10
SadBunny

poll: 0非同期アクション を使用するだけです。

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

これらのオプションは、ans-ibleが os.killpg でそのタスクの子プロセスを強制終了しないようにするために必要です。

次にyourscript.shで:

Java Test &
disown

disownはプロセスをジョブテーブルから削除するため、SIGHUPはプロセスに送信されません。 Nohupも同じことを行いますが、必須ではありません。

Edit:すべてのシェルでdisownを使用できるわけではないことに注意してください(例:ダッシュ)

18
user1338062

Start-stop-daemonを使用してデーモンとしてスクリプトを実行することは、ここではよりエレガントなソリューションのように見えます。 http://manpages.ubuntu.com/manpages/raring/man8/start-stop-daemon.8.html

- name: Start application
  Shell: "start-stop-daemon --start --quiet --pidfile /var/run/test --exec /tmp/test.sh"
  args:
    executable: "/bin/bash"
7
MillerGeek

Googleサーバーは今までに喫煙しているはずですが、解決策を見つけました。 Ansibleがすべてのリモートコマンドを個別のssh呼び出しを介して実行することに気付いたとき、それをansibleサーバーから手動で実行してテストし、ssh機能と関係があることを発見しました。

答えは、どうやら、私がダブルバックグラウンドトリックを実行するために呼び出したスクリプトを、Nohupと組み合わせてハングアップシグナル(SIGHUP)を無視し、stdoutとstderrストリームの切断と組み合わせることです。したがって、リモート起動スクリプトは次のことを行いません。

Java Test &

...しかし代わりに今はします:

( ( Nohup Java Test 1>/dev/null 2>&1 ) & )

私がやりたいことをします。 ansible-playbookはリモートスクリプトを起動し、次にJavaアプリケーションを起動しますが、その後、バックグラウンドを二重化してnohupsし、出力ストリームを切断します。

このstackoverflowスレッド は私を助けました。

6
SadBunny