如何使用 Ansible 在远程服务器上执行 shell 脚本?

问题描述 投票:0回答:8

我打算使用 Ansible 剧本在远程服务器上执行 shell 脚本。

空白test.sh文件:

touch test.sh

剧本:

---
- name: Transfer and execute a script.
  hosts: server
  user: test_user
  sudo: yes
  tasks:
     - name: Transfer the script
       copy: src=test.sh dest=/home/test_user mode=0777

     - name: Execute the script
       local_action: command sudo sh /home/test_user/test.sh

当我运行 playbook 时,传输成功但脚本没有执行。

shell ansible remote-server
8个回答
126
投票

你可以使用脚本模块

例子

- name: Transfer and execute a script.
  hosts: all
  tasks:

     - name: Copy and Execute the script 
       script: /home/user/userScript.sh

60
投票

local_action
在本地服务器上运行命令,而不是在您在
hosts
参数中指定的服务器上运行命令。

将“执行脚本”任务更改为

- name: Execute the script
  command: sh /home/test_user/test.sh

它应该这样做。

你不需要在命令行中重复 sudo 因为你已经在剧本中定义了它。

根据 Ansible Intro to Playbooks

user
parameter was renamed to
remote_user
in Ansible 1.4 所以你也应该改变它

remote_user: test_user

所以,剧本将变成:

---
- name: Transfer and execute a script.
  hosts: server
  remote_user: test_user
  sudo: yes
  tasks:
     - name: Transfer the script
       copy: src=test.sh dest=/home/test_user mode=0777

     - name: Execute the script
       command: sh /home/test_user/test.sh

24
投票

最好使用

script
模块:
http://docs.ansible.com/script_module.html


4
投票

对于有人想要一个临时命令

ansible group_or_hostname -m script -a "/home/user/userScript.sh"

或使用相对路径

ansible group_or_hostname -m script -a "userScript.sh"

3
投票

与所有其他答案和评论相反,使用

script
模块有一些缺点。特别是当您在远程(而非本地主机)主机上运行它时。这是官方ansible文档的片段:

通常 编写 Ansible 模块比推送更可取 脚本。 将您的脚本转换为 Ansible 模块以获得奖励积分!

ssh 连接插件将通过 -tt 强制伪 tty 分配 执行脚本时。伪 ttys 没有 stderr 通道 并且所有 stderr 都被发送到 stdout。 如果你依赖分离的标准输出 和 stderr 结果键,请切换到复制+命令任务集 而不是使用脚本。

如果本地脚本的路径包含空格,则需要 引用。

此模块也支持 Windows 目标。

例如,使用

script
模块为除 localhost 以外的任何主机 运行此脚本,并注意脚本的
stdout
stderr

#!/bin/bash


echo "Hello from the script"

nonoexistingcommand

echo "hello again"

你会得到类似下面的东西;注意

stdout
合并了所有
stderr
。(理想情况下
line 6: nonoexistingcommand: command not found
应该在
stderr
中)因此,如果您要在脚本输出的标准输出中搜索某些子字符串。你可能会得到不正确的结果。:

 ok: [192.168.122.83] => {
    "script_out": {
        "changed": true,
        "failed": false,
        "rc": 0,
        "stderr": "Shared connection to 192.168.122.83 closed.\r\n",
        "stderr_lines": [
            "Shared connection to 192.168.122.83 closed."
        ],
        "stdout": "Hello from the script\r\n/home/ps/.ansible/tmp/ansible-tmp-1660578527.4335434-35162-230921807808160/my_script.sh: line 6: nonoexistingcommand: command not found\r\nhello again\r\n",
        "stdout_lines": [
            "Hello from the script",
            "/home/ps/.ansible/tmp/ansible-tmp-1660578527.4335434-35162-230921807808160/my_script.sh: line 6: nonoexistingcommand: command not found",
            "hello again"
        ]
    }
}

文档不鼓励用户使用脚本模块;考虑将你的脚本转换成一个 ansible 模块;这是我写的一篇简单的帖子,解释了如何将您的脚本转换为一个 ansible 模块。 此外,如果您打算将

async/poll
与脚本模块一起使用,则不支持;检查this。 其他一些重要原因,但不限于:

  1. 如果您使用 Python 编写模块,则可以使用

    Ansible Module.
    提供的大量功能。例如,您可以通过在模块中设置
    changed_when
    变量来设置幂等性。 (请参阅@DanOPT 的评论)。

  2. 您可以安全地使用模块内的敏感变量,并通过为特定变量设置

    no_log.
    来保证它的安全。如果您不使用该模块,您有责任保护敏感变量不受日志和标准输出的影响。例子:


password=dict(type='str',
              required=True,
              no_log=True)

1
投票

如果脚本在本地机器上存在,您可以使用模板模块复制到远程机器并执行它。

 - name: Copy script from local to remote machine
   hosts: remote_machine
   tasks:
    - name: Copy  script to remote_machine
      template: src=script.sh.2 dest=<remote_machine path>/script.sh mode=755
    - name: Execute script on remote_machine
      script: sh <remote_machine path>/script.sh

1
投票

由于“脚本”没有任何定义,意味着复杂性、内容、运行时、运行时环境、大小、要执行的任务等都是未知的,因此可以使用不推荐的方法,如“如何使用 Ansible 复制文件中带有特殊字符的命令提示符中提供的内容?"

---
- hosts: test
  become: false
  gather_facts: false

  tasks:

  - name: Exec sh script on Remote Node
    shell:
      cmd: |
        date
        ps -ef | grep ssh
        echo "That's all folks"
    register: result

  - name: Show result
    debug:
      msg: "{{ result.stdout }}"

这只是一个多行shell命令(注释:...只是内联代码)并导致输出

TASK [Show result] ****************************************************
ok: [test.example.com] =>
  msg: |-
    Sat Sep 3 21:00:00 CEST 2022
    root        709      1  0 Aug11 ?        00:00:00 /usr/sbin/sshd -D
    root     123456    709 14 21:00 ?        00:00:00 sshd: user [priv]
    user     123456 123456  1 21:00 ?        00:00:00 sshd: user@pts/0
    root     123456 123456  0 21:00 pts/0    00:00:00 grep ssh
    That's all folks

可以添加更多行、复杂性、必要的输出等。


因为

script
模块-传输后在远程节点上运行本地脚本-注释

编写 Ansible 模块通常比推送脚本更可取。

我还建议熟悉编写自己的模块,正如P....的答案中已经提到的那样


0
投票

你可以在ansible上执行本地脚本,而不必将文件传输到远程服务器,这样:

ansible my_remote_server -m shell -a "`cat /localpath/to/script.sh`"
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.