Score:0

Ansible 'command' task missing 'stdout' for 'nginx' config verification

ng flag

After deploy new configuration of Nginx, I would like to verify configuration before Nginx handler for reload is applied. This is output of command line:

nginx -t && echo $?
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
0

Based on output above, I configured Ansible command task like this:

- name: Verify Nginx config
  become: yes
  command: nginx -t
  register: nginx_verify_config
  check_mode: no
  changed_when: "'syntax is ok' not in nginx_verify_config.stdout"

- debug:
    msg: "{{nginx_verify_config.stdout}}"

changed_when should show something changed only if output of command is mising syntax is ok. This does not work and I found out, the message in nginx_verify_config looks like this:

ok: [DevNgx] => {
    "msg": {
        "changed": true,
        "cmd": [
            "nginx",
            "-t"
        ],
        "delta": "0:00:00.018083",
        "end": "2023-04-14 14:44:16.656261",
        "failed": false,
        "msg": "",
        "rc": 0,
        "start": "2023-04-14 14:44:16.638178",
        "stderr": "nginx: the configuration file /etc/nginx/nginx.conf syntax is ok\nnginx: configuration file /etc/nginx/nginx.conf test is successful",
        "stderr_lines": [
            "nginx: the configuration file /etc/nginx/nginx.conf syntax is ok",
            "nginx: configuration file /etc/nginx/nginx.conf test is successful"
        ],
        "stdout": "",
        "stdout_lines": []
    }
}

Why is message stored under stderr sections msg and stdout are empty?

I tried to add 2>&1 at the end of the command, but it raised error nginx: invalid option: "2>&1".

in flag
`Why is message stored under stderr sections msg and stdout are empty?` because the nginx developers programmed it that way.
Score:2
cn flag

Instead of relying on string output you can check the return code itself (nginx will return non-zero rc if config is not valid):

- name: check nginx configuration
  become: yes
  command: "nginx -t"
  register: nginx_verify_config
  check_mode: no
  changed_when: "nginx_verify_config.rc != 0"

You should also consider checking a config file pre-deployment, that is run nginx -t -c /path/to/conf-file in your validator before you deploy the config, as otherwise your state change is inconsistent and you have to deal with rolling back the changes that may result in a whole lot of other problems..

dorinand avatar
ng flag
I do not rely on string output. Task will fail if rc is not zero by default. Changed_when just does not show yellow task but green. So in ansible summary you do not see changes. This will be always as change, because command runs every time. I agree with your point about pre-deploymnet config check, I just past simple example of my issue here.
Peter Zhabin avatar
cn flag
Well, the thing is that the code I proposed differs from yours only in the way it evaluates `changed_when`, it does exactly the same thing otherwise. Maybe you chould clarify your question a bit to describe what problem you're trying to solve?
Ginnungagap avatar
gu flag
In any case, `changed_when` should be false for the task since it does not change anything. It can be either ok with no change or failed because the configuration check failed.
dorinand avatar
ng flag
@PeterZhabin my question is why the message of command is not in stdout section but in stderr? I know what I want to have in `change_when` it just does not work because of output of command task. If I change `"'syntax is ok' not in nginx_verify_config.stdout"` to `"'syntax is ok' not in nginx_verify_config.stderr"` it starts working.
dorinand avatar
ng flag
@Ginnungagap I do not think it should be set to `false` in any case. [Here](https://www.middlewareinventory.com/blog/ansible-changed_when-and-failed_when-examples/) is an example of when to set it to condition like I have.
Ginnungagap avatar
gu flag
I don't see anything in what you link that remotely suggest having tasks that change nothing be marked as changed. The linked examples are about commands that actually may change something when run. In our current situation, the command never changes anything. So yes, it should be set to `false`.
Score:1
ca flag

Why is message stored under stderr sections msg and stdout are empty?

Because

This is how it works since introduction - nginx consistently uses stderr for all output

according Why write nginx version on stderr?

Other software packages like Java or Python are reporting his version to stderr too.

For validating the nginx.conf during a deployment with Ansible you may also have a look into


I tried to add 2>&1 at the end of the command, but it raised error nginx: invalid option: "2>&1".

That is also the expected behavior for command module – Execute commands on targets

The command(s) will not be processed through the shell, so variables like $HOSTNAME and operations like *, <, >, |, ; and & will not work. Use the ansible.builtin.shell module if you need these features.

I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.