如何使用Ansible Shell模块运行远程命令

Ansible 核心为几乎所有用例提供了数百个 Ansible 模块。您可以在Ansible 文档页面上找到所有 Ansible 模块的完整列表及其描述。有时,您只需要像在 bash shell 上一样直接在目标主机上执行命令。这就是 Ansible shell 模块派上用场的地方。在本指南中,您将了解 Ansible shell 模块、它的工作原理以及如何使用它对托管节点执行命令。

什么是 Ansible Shell 模块?

Ansible shell 模块是一个方便的模块,它允许您直接在远程目标的 shell 上执行命令,就像您已登录一样。这样做有助于保持命令执行的原创性。

shell 模块与命令模块密切相关。两者都有助于实现相同的结果。但是,两者之间存在一些差异:

  • shell 模块直接在目标主机的 shell 上执行命令。默认情况下,shell 模块使用/bin/shshell 来运行命令,尽管您可以将其配置为使用其他 shell。使用 command 模块,执行的命令不通过 shell 处理。
  • 由于命令不在 shell 上执行,命令模块不支持环境变量、管道和其他运算符,例如 '>' 、 '<' 、 '&'、';' 和'| |'。使用 shell 模块,完全支持管道、重定向和变量。因此,shell 模块提供了更大的灵活性。
  • 如果在目标系统上安全地运行命令是您的首要任务,请使用命令模块。与 shell 模块不同,command 模块不影响远程用户的 shell 环境。

Ansible Shell 模块与其他模块

commandAnsible shell 模块与、script和模块属于同一类别raw。这些统称为运行命令。

虽然可以快速高效地完成任务,但运行命令只能​​作为最后的手段使用。这是因为它们在执行任务时应用最少的逻辑,并且不存在所需状态的概念。如果已经满足导致错误的条件,则 shell 命令的后续执行可能会失败。

此外,除非您注册第一个命令的结果,否则无法使用 shell 模块捕获错误。然后,您必须在剧本中执行后续任务以实施条件逻辑来确认错误是否发生,然后进行处理。这可能会导致严重破坏自动化的瓶颈。

出于这个原因,shell 命令应该仅限于在远程系统上执行简单的任务。如果需要服务或应用程序的理想状态,建议使用特定于任务的模块,例如service、copy、file和lineinfile,仅举几例。这使得剧本更加通用和可重用。

先决条件

要遵循本指南,您应该:

  • 一个 Ansible 控制节点。在本教程中,我们运行的是 Ubuntu 20.04。如果您还没有安装 Ansible,请按照我们关于如何在 Ubuntu 20.04 上安装和配置 Ansible的指南进行操作。
  • 您将对其运行命令的远程主机。

运行 Ansible Ad-hoc Shell 命令

Ansible 的真正力量在于剧本。但是,剧本用于在目标主机上执行复杂的任务。假设您想要非常快速地运行命令而不保存它们供以后使用。你会怎么做?这就是临时命令派上用场的地方。

Ad-hoc 命令是单行命令,您无需编写剧本即可即时运行。

例如,您可能想要检查远程主机的正常运行时间或磁盘空间利用率。与其为此类任务编写完整的剧本,更好的方法是对您的主机运行临时命令。

临时命令采用以下语法:

ansible [pattern] -m [MODULE] -a {COMMAND_OPTIONS}

该模式指定目标主机所属的主机组。该-m选项指定模块的类型,而该-a选项采用命令参数。

让我们举几个例子。

要检查所有目标主机的正常运行时间,请运行以下命令:

sudo ansible all -m shell -a 'uptime -p'

如何使用Ansible Shell模块运行远程命令

要检查内存使用情况,请运行:

sudo ansible all -m shell -a 'free -m'

如何使用Ansible Shell模块运行远程命令

查看db_server组下主机的磁盘空间利用率,执行:

sudo ansible db_server -m shell -a 'df -Th'

如何使用Ansible Shell模块运行远程命令

使用 Ansible Shell 模块运行单个命令

除了运行临时命令外,Ansible shell 模块还用于 playbook 以指定要在远程主机上执行的任务。

考虑下面的剧本。

---
- name: Shell module example
  hsots: webservers
  tasks:
  
  - name: Check system information
    shell:
    	"lsb_release -a"
    register: os_info
    
  - debug:
    	msg: "{{os_info.stdout_lines}}"

在此示例中,剧本针对名为 webservers 的主机组运行,并执行一个lsb_release -a命令来检索有关操作系统版本的详细信息。然后将输出保存在一个名为 的寄存器变量中os_info。

最后一行使用模块将存储在os_info变量中的输出打印到标准输出。debug

这是剧本执行的输出。

如何使用Ansible Shell模块运行远程命令

如果文件不存在,则使用 Shell 模块运行命令

该creates参数允许您在文件不存在时运行命令。它指定文件的路径,如果存在,则跳过要执行的命令。

显示的剧本检查文件是否hello.txt存在于目标主机的主目录中。如果该文件不存在,则执行指定的 shell 命令。如果该文件存在,则 shell 命令将中止。

---
- name: Create a file in the home directory if it doesn't exist
  hosts: webservers
  tasks:
  	- name: Create a file in the home directory
      shell: echo "Hey guys!" > $HOME/hello.txt
      args:
      	creates: "$HOME/hello.txt"

由于该文件在远程目标上不存在,因此 shell 命令已成功执行,如您从 playbook 执行中所见。

如何使用Ansible Shell模块运行远程命令

下面的命令确认hello.txt文件是在远程目标的主目录中创建的。

ssh root@173.82.120.115 "ls -l ~"

如何使用Ansible Shell模块运行远程命令

如果文件存在,则使用 Shell 模块运行命令

参数指定文件名,removes如果文件存在,则执行命令。在前面的示例中,该hello.txt文件是在远程目标的主目录中创建的。

在此剧本中,removes参数检查此文件是否存在于远程目标上。由于您已经创建了它,剧本会继续执行删除文件的 shell 命令。

---
- name: Remove a file in the home directory only if it exists
  hosts: webservers
  tasks:
  	- name: Remove a file in the home directory
      shell: rm $HOME/hello.txt
      args:
      	removes: "$HOME/hello.txt"
        warn: false

剧本执行确认文件已被删除。

如何使用Ansible Shell模块运行远程命令

在不同的目录中运行命令

要在特定目录中运行 shell 命令,请使用chdir参数。下面的剧本将 Apache 二进制文件下载到/usr/local/src路径中。

---
- name: Download Apache source file to /usr/local/src directory
  hosts: webservers
  tasks:
  	- name: Download Apache tarball file
      shell: wget https://dlcdn.apache.org/httpd/httpd-2.4.52.tar.gz
      args:
      	chdir: /usr/local/src
        warn: false

剧本确认任务已成功执行。

如何使用Ansible Shell模块运行远程命令

将 Ansible shell 模块与环境变量一起使用

shell 模块还使您能够设置新的环境变量。使用environment参数可以做到这一点。考虑下面的剧本。

---
- name: Environment variable example
  hosts: webservers
  tasks:
  	- name: Ansible Shell module set an environment variable
      shell: echo $NEW_VAR
      register: command_result
      envnironment:
      	NEW_VAR: "john_doe"
    - debug: 
      	msg: "{{ command_result.stdout_lines }}"

该剧本将NEW_VAR环境变量设置为john_doe。

注意:环境变量仅为该特定任务设置。在后续任务中,NEW_VAR 变量将不可用。

如何使用Ansible Shell模块运行远程命令

使用 Ansible Shell 模块运行多个命令

到目前为止,您已经看到 shell 模块在托管主机上运行单个命令。您还可以指定一组按时间顺序执行的命令。

要实现这一点,请使用竖线开始 shell 命令,然后是要执行的任务列表。在本例中,date、uptime、 和echo命令的输出分别保存到date.txt、uptime.txt和hello.txt文件中,然后保存在/tmp目录中。

---
- name: Shell module example
  hsots: webservers
  tasks:
  	- name: Run multiple commands
     shell: |
     	date > /tmp/date.txt
       uptime > /tmp/uptime.txt
       echo "Hello World" > /tmp/hello.txt

剧本从第一个任务到最后一个任务按顺序运行任务。

如何使用Ansible Shell模块运行远程命令

使用管道和重定向运行命令

如前所述,shell 模块也接受管道和重定向。事实上,之前的剧本利用重定向符号 ( >) 将列出的命令的输出保存到单独的文件中。

假设您要列出在/tmp目录中创建的所有文本文件,并将结果保存到同一目录中另一个名为dirlist.txt的文件中。

这是 shell 命令的样子。

ls -l /tmp | grep .txt > /tmp/dirlist.txt

命令的第一部分列出了/tmp目录中的所有文件。然后将结果通过管道传输到 grep 命令,该命令过滤输出以仅包含文本文件。然后使用“大于”重定向符号将最终输出保存到dirlist.txt文件。

现在让我们更进一步,将结果打印到标准输出。为此,需要第二项任务。目标是将dirlist.txt文件的内容显示到标准输出。列出文件内容的 shell 命令是:

cat /tmp/dirlist.txt

命令的输出随后被注册在一个名为displayfile的变量中,并且使用调试模块将消息显示到标准输出。这是整个剧本的样子。

---
- name: Shell module example
  hosts: webservers
  tasks:
  	- name: List text files in tmp directory and save result in output file
      shell: "ls -l /tmp | grep .txt > /tmp/dirlist.txt
      
    - name: Display the contents of the output file
      shell: cat /tmp/dirlist.txt
      register: displayfile
      
    - debug:
      	msg: "{{ displayfile.stdout_lines }}"

执行 playbook 时,/tmp目录中的所有文本文件(包括dirlist.txt文件)都会打印到标准输出:

如何使用Ansible Shell模块运行远程命令

防止 Shell 注入

由于它在远程目标的 shell 上运行命令,因此 shell 模块容易受到 shell 命令注入。Shell 注入是一种攻击媒介,攻击者在其中在主机上运行任意命令以破坏底层基础设施。

使用 Shell 模块变量时,Ansible 建议使用quote过滤器来阻止 shell 注入威胁。

{{ variable_name | quote }}

考虑下面的一个简单剧本。

---
- name: Ansible quote filter demo
  hosts: webservers
  vars:
    - username: cherry
      
  tasks:
    - name: Print variable
      debug:
        msg: " Running playbook as user {{ username | quote }}

该username变量在最后由msg使用过滤器的参数引用,quote以防止在注入用户名变量时执行任意命令字符串。

结论

Ansible shell 模块是一个有用的模块,可以帮助您在托管主机上快速执行简单任务。shell 模块的完美替代品是commandmodule。它提供了一种更可靠、更安全的任务执行方式,因为命令不会在远程目标的 shell 上处理。但是,如果您坚持使用 shell 模块,请不要忘记quote在 playbook 中使用模板化变量时包含过滤器以防止 shell 注入攻击。

文章链接: https://www.mfisp.com/13556.html

文章标题:如何使用Ansible Shell模块运行远程命令

文章版权:梦飞科技所发布的内容,部分为原创文章,转载请注明来源,网络转载文章如有侵权请联系我们!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

给TA打赏
共{{data.count}}人
人已打赏
IDC云库

如何设置、列出和管理Linux环境变量

2022-12-1 15:20:53

IDC云库

利用IaaS的力量

2022-12-1 16:49:30

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
客户经理
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索

梦飞科技 - 最新云主机促销服务器租用优惠