我正在寻找一种使用Ansible运行Postgres脚本的方法。虽然我找到了一个相当不错的例子Here,但我需要:
任何人都可以告诉我这是否可行,如果是这样的话,可以运行它。这是我到目前为止使用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
登录图像数据库时,它始终挂在它的第一部分。
答案 0 :(得分:23)
此:
- 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
没有做你认为的事情。
第一个命令运行psql -U bob image
。这将启动psql
会话。 psql
等待stdin的输入。 Ansible永远不会发送任何内容,只是等待你指定的命令退出,所以它可以检查退出代码。
所以Ansible等待psql
退出,psql
等待Ansible发送一些输入。
Ansible的每项任务都是独立的。 shell
或command
模块不会更改后续命令运行的shell。您根本无法按照预期的方式执行此操作。
即使在第一项任务之后退出psql
(或转到后台),您也会从第二项任务中收到错误,例如:
bash: d: command not found
因此,您尝试这样做的方式并不适用。
您需要将每个任务作为单独的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'
...或标准输入,但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
或者,您可以使用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
答案 1 :(得分: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'
注意“成为”和“成为_用户”参数。这些将告诉Ansible在运行命令之前更改为正确的用户。
重要提示:Ansible 1.9及更早版本使用sudo: yes
和sudo_user: postgres
代替become: true
和become_user: postgres
答案 2 :(得分:4)
基于上面的优秀响应,您还可以在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 }}"