複数のリモートコンピュータでパラメータを使用してスクリプトを実行および停止する方法

複数のリモートコンピュータでパラメータを使用してスクリプトを実行および停止する方法

10年前、こんな質問がありました。多くのサーバーでSSHを介したコマンド実行の自動化

デフォルトでは、同じ操作がありますが(おそらく異なる場合があります)、パラメーターを使用してコマンド/スクリプトを実行し、長期実行操作を停止する必要があります。また、どのスクリプトが実行されているか完了していて、結果が何であるかを監視できるように、最新のモニター(少なくともWeb UIやElastic出力など)を好みます。最終的に並べるか、時間を制限することをお勧めします。また、すべてのコンピュータに自分の公開鍵を追加することはできませんが、そこにいくつかのソフトウェアをインストールさせることもできます。

これは主にAIトレーニングプロセスに使用されますが、フレームワークをアップグレードし、最終的に新しいスクリプトとデータを転送(ダウンロード)するためにも使用されます。

上記のリンクでは、誰もがAnsibleの使用を提案しましたが、私は自動化方式が現代的な方法だと思いますが、他の方法はありませんか?

友達もCI / CD(gitlab作業)を提案しましたが、それは少し過度だと思われ、コードテストのような他の目的に使用しました。 AutoMLに関するヒントも得られましたが、これは完全なAIフレームワークであり、さまざまなパラメータを使用して複数のコマンド/スクリプトを実行する必要があるため必要ありません。

ベストアンサー1

パラメータを辞書に入れます。

  • たとえば、デフォルトから始めましょう。
shell> cat group_vars/all/scripts.yml
scripts:
  default:
    script: /root/bin/default.sh
    params: p1 p2 p3
    timeout: 30
    retries: 10
    delay: 3
    log: /tmp/ansible_script.log

特定のコントローラのスクリプト

shell> tree files
files
├── default.sh
├── script_A.sh
├── script_B.sh
└── script_C.sh
shell> cat files/default.sh 
#!/bin/sh
echo $1 $2 $3
echo finished > /tmp/ansible_script.log
exit 0

以下のスクリプト

shell> cat pb.yml
- hosts: all

  vars:
    my_script: "{{ scripts[inventory_hostname]|d(scripts['default']) }}"
    _script: "{{ my_script.script|d(scripts.default.script) }}"
    _params: "{{ my_script.params|d(scripts.default.params) }}"
    _timeout: "{{ my_script.timeout|d(scripts.default.timeout) }}"
    _retries: "{{ my_script.retries|d(scripts.default.retries) }}"
    _delay: "{{ my_script.delay|d(scripts.default.delay) }}"
    _log: "{{ my_script.log|d(scripts.default.log) }}"

  tasks:
    - debug:
        msg: |-
          _script: {{ _script }}
          _params: {{ _params }}
          _timeout: {{ _timeout }}
          _retries: {{ _retries }}
          _delay: {{ _delay }}
          _log: {{ _log }}
      when: debug|d(false)|bool

    - name: Copy script
      block:
        - file:
            state: directory
            path: "{{ _script|dirname }}"
            mode: 0750
        - copy:
            src: "{{ _script|basename }}"
            dest: "{{ _script }}"
            mode: 0550
      when: copy_script|d(false)|bool

    - name: Run script
      block:
        - command:
            cmd: "{{ _script }} {{ _params }}"
          async: "{{ _timeout }}"
          poll: 0
          register: cmd_async
        - debug:
            var: cmd_async.ansible_job_id
          when: debug|d(false)|bool

    - name: Read log until finished
      block:
        - command:
            cmd: "cat {{ _log }}"
          register: cmd_log
          until: cmd_log.stdout == 'finished'
          retries: "{{ _retries }}"
          delay:  "{{ _delay }}"
        - debug:
            var: cmd_log.stdout
          when: debug|d(false)|bool
      when: read_log_fin|d(false)|bool

    - name: Check async script
      block:
        - async_status:
            jid: "{{ cmd_async.ansible_job_id }}"
          register: job_result
          until: job_result.finished
          retries: "{{ _retries }}"
          delay: "{{ _delay }}"
        - debug:
            msg: >-
              {{ job_result.start }}
              {{ job_result.end }}
              rc: {{ job_result.rc}}
          when: debug|d(false)|bool

与えられた

shell> ansible-playbook pb.yml -e debug=true -e copy_script=true -e read_log_fin=true

PLAY [all] ***********************************************************************************

TASK [debug] *********************************************************************************
ok: [test_11] => 
  msg: |-
    _script: /root/bin/default.sh
    _params: p1 p2 p3
    _timeout: 30
    _retries: 10
    _delay: 3
    _log: /tmp/ansible_script.log
ok: [test_12] => 
  msg: |-
    _script: /root/bin/default.sh
    _params: p1 p2 p3
    _timeout: 30
    _retries: 10
    _delay: 3
    _log: /tmp/ansible_script.log
ok: [test_13] => 
  msg: |-
    _script: /root/bin/default.sh
    _params: p1 p2 p3
    _timeout: 30
    _retries: 10
    _delay: 3
    _log: /tmp/ansible_script.log

TASK [file] **********************************************************************************
ok: [test_13]
ok: [test_12]
ok: [test_11]

TASK [copy] **********************************************************************************
ok: [test_12]
ok: [test_11]
ok: [test_13]

TASK [command] *******************************************************************************
changed: [test_12]
changed: [test_11]
changed: [test_13]

TASK [debug] *********************************************************************************
ok: [test_11] => 
  cmd_async.ansible_job_id: '754707567219.90860'
ok: [test_12] => 
  cmd_async.ansible_job_id: '148176661548.90862'
ok: [test_13] => 
  cmd_async.ansible_job_id: '688240445475.90861'

TASK [command] *******************************************************************************
changed: [test_13]
changed: [test_11]
changed: [test_12]

TASK [debug] *********************************************************************************
ok: [test_11] => 
  cmd_log.stdout: finished
ok: [test_12] => 
  cmd_log.stdout: finished
ok: [test_13] => 
  cmd_log.stdout: finished

TASK [async_status] **************************************************************************
changed: [test_12]
changed: [test_13]
changed: [test_11]

TASK [debug] *********************************************************************************
ok: [test_11] => 
  msg: '2022-08-01 16:02:50.287027 2022-08-01 16:02:50.320177 rc: 0'
ok: [test_12] => 
  msg: '2022-08-01 16:02:49.770331 2022-08-01 16:02:49.801347 rc: 0'
ok: [test_13] => 
  msg: '2022-08-01 16:02:50.189800 2022-08-01 16:02:50.343773 rc: 0'

PLAY RECAP ***********************************************************************************
test_11: ok=9    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_12: ok=9    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_13: ok=9    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

  • 繰り返し中は中間ログを表示できません。コールバックプラグインは、反復後にすべての結果をまとめて表示します。中間ログを観察するには、Ansibleから出る必要があります。たとえば、ログファイルをインポートします。
    - name: Fetch log until finished
      fetch:
        dest: /tmp/ansible/
        src: "{{ _log }}"
      until: lookup('file', my_logfile) == 'finished'
      retries: "{{ _retries }}"
      delay:  "{{ _delay }}"
      vars:
        my_logfile: "/tmp/ansible/{{ inventory_hostname}}/tmp/ansible_script.log"
      when: fetch_log_fin|d(false)|bool

これにより、コントローラに定期的に更新されるファイルが生成されます。

shell> tree /tmp/ansible/
/tmp/ansible/
├── test_11
│   └── tmp
│       └── ansible_script.log
├── test_12
│   └── tmp
│       └── ansible_script.log
└── test_13
    └── tmp
        └── ansible_script.log

コントローラにファイルを表示します。例えばより

shell> watch cat /tmp/ansible/test_11/tmp/ansible_script.log

これをテストするために、次のスクリプトは$ 2間隔でログに$ 1回書き込みます。

shell> cat files/script_A.sh
#!/bin/sh
for i in $(seq 1 $1); do
    echo step $i  > /tmp/ansible_script.log
    sleep $2
done
echo finished > /tmp/ansible_script.log
exit 0

ポスターを見るために辞書を更新してください。テスト_11スクリプトの実行

shell> cat group_vars/all/scripts.yml
scripts:
  default:
    script: /root/bin/default.sh
    params: p1 p2 p3
    timeout: 30
    retries: 10
    delay: 3
    log: /tmp/ansible_script.log
  test_11:
    script: /root/bin/script_A.sh
    params: 7 3

スクリプトには要約が含まれています。 (プレイブックを再実行する前にインポートしたファイルを削除してください。そうしないと、最後のファイルからジョブをスキップします。)

shell> ansible-playbook pb.yml -e debug=true -e fetch_log_fin=true
...
TASK [Fetch log until finished] **************************************************************
ok: [test_12]
FAILED - RETRYING: [test_11]: Fetch log until finished (10 retries left).
ok: [test_13]
FAILED - RETRYING: [test_11]: Fetch log until finished (9 retries left).
FAILED - RETRYING: [test_11]: Fetch log until finished (8 retries left).
FAILED - RETRYING: [test_11]: Fetch log until finished (7 retries left).
FAILED - RETRYING: [test_11]: Fetch log until finished (6 retries left).
changed: [test_11]

TASK [async_status] **************************************************************************
changed: [test_13]
changed: [test_12]
changed: [test_11]

TASK [debug] *********************************************************************************
ok: [test_11] => 
  msg: '2022-08-01 18:00:13.304133 2022-08-01 18:00:34.768385 rc: 0'
ok: [test_12] => 
  msg: '2022-08-01 18:00:13.413492 2022-08-01 18:00:13.480142 rc: 0'
ok: [test_13] => 
  msg: '2022-08-01 18:00:13.537767 2022-08-01 18:00:13.731926 rc: 0'

PLAY RECAP ***********************************************************************************
test_11: ok=6    changed=3    unreachable=0    failed=0    skipped=4    rescued=0    ignored=0   
test_12: ok=6    changed=2    unreachable=0    failed=0    skipped=4    rescued=0    ignored=0   
test_13: ok=6    changed=2    unreachable=0    failed=0    skipped=4    rescued=0    ignored=0

ログを読むと、出力はほぼ同じです。

shell> ansible-playbook pb.yml -e debug=true -e read_log_fin=true
...
TASK [Read log until finished] ***************************************************************
FAILED - RETRYING: [test_11]: Read log until finished (10 retries left).
changed: [test_12]
changed: [test_13]
FAILED - RETRYING: [test_11]: Read log until finished (9 retries left).
FAILED - RETRYING: [test_11]: Read log until finished (8 retries left).
FAILED - RETRYING: [test_11]: Read log until finished (7 retries left).
FAILED - RETRYING: [test_11]: Read log until finished (6 retries left).
changed: [test_11]

TASK [debug] *********************************************************************************
ok: [test_11] => 
  cmd_log.stdout: finished
ok: [test_12] => 
  cmd_log.stdout: finished
ok: [test_13] => 
  cmd_log.stdout: finished

フルスクリプトpb.ymlへのリンク

おすすめ記事