简体   繁体   English

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

[英]How to execute a shell script on a remote server using Ansible?

I am planning to execute a shell script on a remote server using Ansible playbook.我计划使用 Ansible 剧本在远程服务器上执行 shell 脚本。

blank test.sh file:空白 test.sh 文件:

touch test.sh

Playbook:剧本:

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

When I run the playbook, the transfer successfully occurs but the script is not executed.当我运行剧本时,传输成功,但脚本没有执行。

you can use script module您可以使用脚本模块

Example例子

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

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

local_action runs the command on the local server, not on the servers you specify in hosts parameter. local_action在本地服务器上运行命令,而不是在您在hosts参数中指定的服务器上运行。

Change your "Execute the script" task to将“执行脚本”任务更改为

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

and it should do it.它应该这样做。

You don't need to repeat sudo in the command line because you have defined it already in the playbook.您不需要在命令行中重复 sudo ,因为您已经在剧本中定义了它。

According to Ansible Intro to Playbooks user parameter was renamed to remote_user in Ansible 1.4 so you should change it, too根据Ansible Intro to Playbooks user参数在 Ansible 1.4 中重命名为remote_user所以你也应该改变它

remote_user: test_user

So, the playbook will become:所以,剧本将变成:

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

It's better to use script module for that:最好为此使用script模块:
http://docs.ansible.com/script_module.html http://docs.ansible.com/script_module.html

For someone wants an ad-hoc command对于想要临时命令的人

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

or use relative path或使用相对路径

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

Contrary to all the other answers and comments, there are some downsides to using the script module.与所有其他答案和评论相反,使用script模块有一些缺点。 Especially when you are running it on a remote(not localhost) host.特别是当您在远程(不是本地主机)主机上运行它时。 Here is a snippet from the official ansible documentation :这是官方 ansible 文档的片段:

It is usually preferable to write Ansible modules rather than pushing scripts.通常最好编写 Ansible 模块而不是推送脚本。 Convert your script to an Ansible module for bonus points!将您的脚本转换为 Ansible 模块以获得奖励积分!

The ssh connection plugin will force pseudo-tty allocation via -tt when scripts are executed. ssh 连接插件将在执行脚本时通过 -tt 强制分配伪 tty。 Pseudo-ttys do not have a stderr channel and all stderr is sent to stdout.伪 tty 没有标准错误通道,所有标准错误都发送到标准输出。 If you depend on separated stdout and stderr result keys, please switch to a copy+command set of tasks instead of using script.如果您依赖分离的 stdout 和 stderr 结果键,请切换到复制+命令任务集,而不是使用脚本。

If the path to the local script contains spaces, it needs to be quoted.如果本地脚本的路径包含空格,则需要加引号。

This module is also supported for Windows targets. Windows 目标也支持此模块。

For example, run this script using script module for any host other than localhost and notice the stdout and stderr of the script.例如,使用script模块为localhost 之外的任何主机运行此脚本,并注意脚本的stdoutstderr

#!/bin/bash


echo "Hello from the script"

nonoexistingcommand

echo "hello again"

You will get something like the below;你会得到类似下面的东西; notice the stdout has all the stderr merged.(ideally line 6: nonoexistingcommand: command not found should be in stderr ) So, if you are searching for some substring in stdout in the script output.请注意stdout已合并所有stderr 。(理想情况下, line 6: nonoexistingcommand: command not found应该在stderr中)因此,如果您在脚本 output 的标准输出中搜索一些 substring。 you may get incorrect results.:您可能会得到不正确的结果。:

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

The documentation is not encouraging users to use the script module;该文档不鼓励用户使用脚本模块; consider converting your script into an ansible module;考虑将您的脚本转换为 ansible 模块; here is a simple post by me that explains how to convert your script into an ansible module.这是我的一个 简单帖子,解释了如何将您的脚本转换为 ansible 模块。

You can execute local scripts at ansible without having to transfer the file to the remote server, this way:您可以在 ansible 执行本地脚本,而无需将文件传输到远程服务器,这样:

ansible my_remote_server -m shell -a "`cat /localpath/to/script.sh`"

Since nothing is defined about "the script" , means complexity, content, runtime, runtime environment, size, tasks to perform, etc. are unknown, it might be possible to use an unrecommended approach like in " How to copy content provided in command prompt with special chars in a file using Ansible? "由于没有关于“脚本”的任何定义,意味着复杂性、内容、运行时、运行时环境、大小、要执行的任务等都是未知的,因此可以使用不推荐的方法,例如“如何复制命令中提供的内容使用 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 }}"

which is a multi-line shell command only and resulting into an output of这是一个多行 shell 命令,并导致 output

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

One could just add more lines, complexity, necessary output, etc.可以添加更多行、复杂性、必要的 output 等。


Because of script module – Runs a local script on a remote node after transferring it - Notes由于script模块 - 传输后在远程节点上运行本地脚本 - 注释

It is usually preferable to write Ansible modules rather than pushing scripts.通常最好编写 Ansible 模块而不是推送脚本。

I also recommend to get familar with writing an own module and as already mentioned in the answer of P....我还建议熟悉编写自己的模块,正如P.... 的答案中已经提到的那样

You can use template module to copy if script exists on local machine to remote machine and execute it.您可以使用模板模块将本地机器上是否存在脚本复制到远程机器并执行它。

 - 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM