blockinfile help

Hello,
I am trying to update nginx file, I need to add 4 more lines before the ; I tried blockinfile, lineinfile, replace and sed but I am unable to get the required output
ex: the below one is some part of my nginx file,
log_format main '$remote_addr - $remote_user [$time_local] “$request” ’
'$status $body_bytes_sent “$http_referer” ’
‘“$http_user_agent” “$http_x_forwarded_for”’;

I need to add '$request_time ’ '$upstream_response_time ’ ‘$upstream_connect_time’ ‘$upstream_header_time’ to the existing line before the ;
blockinfile is somewhat worked but the nginx file end up having ; after ‘“$http_user_agent” “$http_x_forwarded_for”’
my desired output is
log_format main '$remote_addr - $remote_user [$time_local] “$request” ’
'$status $body_bytes_sent “$http_referer” ’
‘“$http_user_agent” “$http_x_forwarded_for”’ '$request_time ’ '$upstream_response_time ’ ‘$upstream_connect_time’ ‘$upstream_header_time’ ;

someone please help me with a solution, I have lot of servers across multiple environments which cannot be done manually.

Something like this, perhaps:

    - name: Do the a.b.replace thing
      ansible.builtin.replace:
        path: narmada-0.txt
        regexp: '^log_format +main +[^;]+;\n'
        replace: 'log_format main {{ bits | map("quote") | join("\n     ") }};\n'
      vars:
        bits:
          - '$remote_addr - $remote_user [$time_local] "$request" '
          - '$status $body_bytes_sent "$http_referer" '
          - '"$http_user_agent" "$http_x_forwarded_for"'
          - '$request_time '
          - '$upstream_response_time '
          - '$upstream_connect_time'
          - '$upstream_header_time'

Thankyou, I tried the above playbook, there is no syntax error but it is not changing anything.

Then, um, fix what’s wrong. (?) I’d be more specific, but you didn’t give me much to work with. Post the task and relevant variables.
Note the “path:” I used on my localhost isn’t what you need.
Also, I didn’t add the those extra data you want to add:

'$request_time ’ '$upstream_response_time ’ ‘$upstream_connect_time’ ‘$upstream_header_time’

it should be obvious where that would go, but if not, post with some details - tasks, variables, and output - and we’ll help you get it working.
One last thing if you aren’t already doing it: use “-D” or “–diff” on the command line to see the changes.

yes, I modified the playbook to my data accordingly …

  • name: replace log_format settings on nginx
    ansible.builtin.replace:
    path: /nginx/nginx.conf
    regexp: ‘^log_format +main +[^;]+;\n’
    replace: ‘log_format main {{ bits | map(“quote”) | join("\n ") }};\n’
    vars:
    bits:
  • '$remote_addr - $remote_user [$time_local] “$request” ’
  • '$status $body_bytes_sent “$http_referer” ’
  • ‘“$http_user_agent” “$http_x_forwarded_for”’
  • '$request_time ’
  • '$upstream_response_time ’
  • ‘$upstream_connect_time’
  • ‘$upstream_header_time’

ansible-playbook -i inventory nginxupdate.yml

PLAY [update nginx.config] *****************************************************************************************************************************************************************************************************

TASK [ replace log_format settings on nginx ] ************************************************************************************************************************************************************************************************
ok: [servername]

PLAY RECAP *********************************************************************************************************************************************************************************************************************
servername :ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Add “-vv” and “–diff” to your command line.

Can you show us the relevant portion of the file /nginx/nginx.conf so we can try to reproduce? (And you really have that in the root? I’d expect /etc or /opt or /opt/local before /nginx, but, whatever.)

yes the path is /etc/nginx/nginx.conf, in my earlier email I removed that.
this is the portion from the existing nginx file
http {
log_format main '$remote_addr - $remote_user [$time_local] “$request” ’
'$status $body_bytes_sent “$http_referer” ’
‘“$http_user_agent” “$http_x_forwarded_for”’;

access_log /var/log/nginx/access.log main;

}

There’s the problem, and also why it’s so important to include all the relevant details up front.

The regexp starts with “^log_format”, i.e. it’s expecting the ‘l’ of “log” to be in the first column, but you’ve got leading white space before “log_format”. Change the regexp line thus:

          regexp: '^\s*log_format +main +[^;]+;\n'

‘\s*’ is zero or more white space characters.

You’ll probably want to add some spaces or tabs to the front of the “replace:” string too.

oh man, this is awesome it worked like a charm, you saved lot of my time

log_format main '$remote_addr - $remote_user [$time_local] “$request” ’
'$status $body_bytes_sent “$http_referer” ’
‘“$http_user_agent” “$http_x_forwarded_for”’
'$request_time ’
'$upstream_response_time ’
‘$upstream_connect_time’
‘$upstream_header_time’;