使用Ansible运行PostgreSQL脚本

rye*_*ayo 13 postgresql ansible

我正在寻找一种使用Ansible运行Postgres脚本的方法.虽然我在这里找到了一个相当不错的例子,但我需要:

  • 以postgres用户身份运行脚本
  • 我不一定需要在服务器上保留脚本的副本,所以如果我需要一个副本,它只会用于临时使用.

任何人都可以告诉我,如果这是可能的,如果是这样的例子,运行它.这是我到目前为止使用Ansible尝试的内容,它只是挂在这些点上:

 - name: Testing DB to make sure it is available
   command: psql -U bob image
   register: b
 - debug: b

 - name: Verifying Tables exist in Image
   shell: \d image
   register: c
 - debug: c

 - name: Exiting Image DB
   shell: \q
   register: d
 - debug: d

 - name: Going to Agent DB
   command: psql -U bob agent
   register: e
 - debug: e
Run Code Online (Sandbox Code Playgroud)

登录图像数据库时,它始终挂在它的第一部分.

Cra*_*ger 24

为什么它不起作用

这个:

 - name: Testing DB to make sure it is available
   command: psql -U bob image
   register: b
 - debug: b

 - name: Verifying Tables exist in Image
   shell: \d image
   register: c
 - debug: c
Run Code Online (Sandbox Code Playgroud)

不会做你认为它做的事情.

第一个命令运行psql -U bob image.这会启动一个psql会话.psql等待stdin的输入.Ansible永远不会发送任何,只是等待你指定的命令退出,所以它可以检查退出代码.

所以Ansible等待psql退出,并psql等待Ansible发送一些输入.

Ansible的每项任务都是独立的.该shellcommand模块不改变后续命令在运行shell,你根本就做不到这一点,你所期望的方式.

即使psql在第一个任务之后退出(或进入后台),你只会从第二个任务中得到错误,如:

bash: d: command not found
Run Code Online (Sandbox Code Playgroud)

所以你试图这样做的方式是行不通的.

怎么做

您需要psql使用命令字符串将每个任务作为单独的命令运行:

 - name: Testing DB to make sure it is available
   command: psql -U bob image -c 'SELECT 1;'

 - name: Verifying Tables exist in Image
   command: psql -U bob image -c '\d image'
Run Code Online (Sandbox Code Playgroud)

...或者使用标准输入,但Ansible似乎不支持将变量作为stdin提供给命令.

...或者(可能是模板化的)SQL脚本:

- name: Template sql script
  template:  src="my.sql.j2" dest="{{sometemplocation}}/my.sql"

- name: Execute sql script
  shell: "psql {{sometemplocation}}/my.sql"

- name: Delete sql script
  file: path="{{sometemplocation}}/my.sql" state=absent
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用Ansible的内置支持来查询PostgreSQL,但在这种情况下,您不能使用psql客户端的反斜杠命令,例如\d,您必须只使用SQL.查询information_schema表信息等

这是我的一些代码看起来如何

这是我编写的自动化模块的一个例子,它对PostgreSQL做了很多工作.

真的,我应该把它psql搞砸并写一个Ansible任务来运行命令psql,而不是使用shell,这是非常糟糕和笨拙的.但就目前而言,它确实有效.我使用从变量分配的连接字符串或使用生成的连接字符串set_fact来减少混乱并使连接更加灵活.

- name: Wait for the target node to be ready to be joined
  shell: "{{postgres_install_dir}}/bin/psql '{{bdr_join_target_dsn}}' -qAtw 'SELECT bdr.bdr_node_join_wait_for_ready();'"

- name: Template pre-BDR-join SQL script
  template:  src="{{bdr_pre_join_sql_template}}" dest="{{postgres_install_dir}}/bdr_pre_join_{{inventory_hostname}}.sql"

- name: Execute pre-BDR-join SQL script
  shell: "{{postgres_install_dir}}/bin/psql '{{bdr_node_dsn}}' -qAtw -f {{postgres_install_dir}}/bdr_pre_join_{{inventory_hostname}}.sql"

- name: Delete pre-BDR-join SQL script
  file: path="{{postgres_install_dir}}/bdr_pre_join_{{inventory_hostname}}.sql" state=absent

- name: bdr_group_join
  shell: "{{postgres_install_dir}}/bin/psql '{{bdr_node_dsn}}' -qAtw -c \"SELECT bdr.bdr_group_join(local_node_name := '{{inventory_hostname}}', node_external_dsn := '{{bdr_node_dsn}}', join_using_dsn := '{{bdr_join_target_dsn}}');\""

- name: Template post-BDR-join SQL script
  template:  src="{{bdr_post_join_sql_template}}" dest="{{postgres_install_dir}}/bdr_post_join_{{inventory_hostname}}.sql"

- name: Execute post-BDR-join SQL script
  shell: "{{postgres_install_dir}}/bin/psql '{{bdr_node_dsn}}' -qAtw -f {{postgres_install_dir}}/bdr_post_join_{{inventory_hostname}}.sql"

- name: Delete post-BDR-join SQL script
  file: path="{{postgres_install_dir}}/bdr_post_join_{{inventory_hostname}}.sql" state=absent
Run Code Online (Sandbox Code Playgroud)


Mil*_*eek 8

Craig给出的答案很好,但未能解决以特定用户身份运行命令的问题.这可以通过添加他的代码来完成:

- name: Testing DB to make sure it is available
  become: true
  become_user: postgres
  command: psql -U bob image -c 'SELECT 1;'

- name: Verifying Tables exist in Image
  become: true
  become_user: postgres
  command: psql -U bob image -c '\d image'
Run Code Online (Sandbox Code Playgroud)

请注意"成为"和"成为用户"参数.这些将告诉Ansible在运行命令之前更改为正确的用户.

重要提示: Ansible 1.9及更早版本使用sudo: yessudo_user: postgres不是become: truebecome_user: postgres


Roy*_*ood 6

基于以上出色的响应,您还可以在Ansible任务中指定环境变量,如下所示。请注意,这假设您已经使用目标数据库的密码设置了一个.pgpass文件。

-   name: Execute some sql via psql
    command: psql -f /path/to/your/sql
    environment:
        PGUSER: "{{ db_user }}"
        PGDATABASE: "{{ db_name }}"
        PGHOST: "{{ db_host }}"
        PGPASS: "{{ pgpass_filepath }}"
Run Code Online (Sandbox Code Playgroud)