我打算使用 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 时,传输成功但脚本没有执行。
你可以使用脚本模块
例子
- name: Transfer and execute a script.
hosts: all
tasks:
- name: Copy and Execute the script
script: /home/user/userScript.sh
local_action
在本地服务器上运行命令,而不是在您在 hosts
参数中指定的服务器上运行命令。
将“执行脚本”任务更改为
- name: Execute the script
command: sh /home/test_user/test.sh
它应该这样做。
你不需要在命令行中重复 sudo 因为你已经在剧本中定义了它。
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
对于有人想要一个临时命令
ansible group_or_hostname -m script -a "/home/user/userScript.sh"
或使用相对路径
ansible group_or_hostname -m script -a "userScript.sh"
与所有其他答案和评论相反,使用
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。
其他一些重要原因,但不限于:
如果您使用 Python 编写模块,则可以使用
Ansible Module.
提供的大量功能。例如,您可以通过在模块中设置 changed_when
变量来设置幂等性。 (请参阅@DanOPT 的评论)。
您可以安全地使用模块内的敏感变量,并通过为特定变量设置
no_log.
来保证它的安全。如果您不使用该模块,您有责任保护敏感变量不受日志和标准输出的影响。例子:
password=dict(type='str',
required=True,
no_log=True)
如果脚本在本地机器上存在,您可以使用模板模块复制到远程机器并执行它。
- 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
由于“脚本”没有任何定义,意味着复杂性、内容、运行时、运行时环境、大小、要执行的任务等都是未知的,因此可以使用不推荐的方法,如“如何使用 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....的答案中已经提到的那样
你可以在ansible上执行本地脚本,而不必将文件传输到远程服务器,这样:
ansible my_remote_server -m shell -a "`cat /localpath/to/script.sh`"