#2464 closed defect (invalid)

nginx doesn't disable stderr logging when using syslog as it does when using a log file

Reported by: thestinger@… Owned by:
Priority: minor Milestone:
Component: nginx-core Version: 1.22.x
Keywords: Cc:
uname -a: Linux raphael 6.2.2-arch1-1 #1 SMP PREEMPT_DYNAMIC Fri, 03 Mar 2023 15:58:31 +0000 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.22.1
built with OpenSSL 3.0.7 1 Nov 2022 (running with OpenSSL 3.0.8 7 Feb 2023)
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --conf-path=/etc/nginx/nginx.conf --sbin-path=/usr/bin/nginx --pid-path=/run/nginx.pid --lock-path=/run/lock/nginx.lock --user=http --group=http --http-log-path=/var/log/nginx/access.log --error-log-path=stderr --http-client-body-temp-path=/var/lib/nginx/client-body --http-proxy-temp-path=/var/lib/nginx/proxy --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-cc-opt='-march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions -Wp,-D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fstack-clash-protection -fcf-protection -flto=auto' --with-ld-opt='-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -flto=auto' --with-compat --with-debug --with-file-aio --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_degradation_module --with-http_flv_module --with-http_geoip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-pcre-jit --with-stream --with-stream_geoip_module --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-threads

Description (last modified by thestinger@…)

When using a file for error_log, nginx replaces stderr with it and avoids logging to the stderr passed by the parent. When using syslog for error_log such as this configuration at the top level, it still logs to stderr:

error_log syslog:server=unix:/dev/log,nohostname;

It also interacts oddly with dynamic configuration reloads. If stderr has already been replaced with a file, it remains that way after reloading with a configuration using syslog instead.

It's possible to work around this by setting error_log to both /dev/null and a syslog output but there will still be an extra unnecessary write system call.

error_log syslog:server=unix:/dev/log,nohostname;
error_log /dev/null;

I don't think this is working as intended. It seems replacing stderr with a file shouldn't be how it's disabled so that it's possible to enable stderr logging in a configuration reload. This would address the current issue where it still happens when using syslog along with making it behave properly for configuration reloads.

Change History (2)

comment:1 by thestinger@…, 21 months ago

Description: modified (diff)

comment:2 by Maxim Dounin, 21 months ago

Resolution: invalid
Status: newclosed

Replying to thestinger@…:

When using a file for error_log, nginx replaces stderr with it and avoids logging to the stderr passed by the parent. When using syslog for error_log such as this configuration at the top level, it still logs to stderr:

error_log syslog:server=unix:/dev/log,nohostname;

Quoting docs:

If on the main configuration level writing a log to a file is not explicitly defined, the default file will be used.

That is, in your configuration (given --error-log-path=stderr in the configure options), logging to syslog is expected to also log to the default file, stderr in your particular case.

This is an explicit behaviour to ensure that:

  • issues with logging to syslog are logged to at least somewhere;
  • stderr output produced by various libraries, if any, is properly redirected to a log file.

If you want to minimize nginx logging to a file, consider using higher logging level, such as emerg.

It also interacts oddly with dynamic configuration reloads. If stderr has already been replaced with a file, it remains that way after reloading with a configuration using syslog instead.

When stderr is redirected to a file and closed, which normally happens when nginx applies a configuration unless stderr is used in it, trying to use stderr (or /dev/stderr) will be essentially equivalent to using the file instead (/dev/null in your case). Note that closing stderr is basically a part of proper daemonization, and not closing it is generally not an option unless explicitly requested.

Overall, the behaviour looks exactly as expected per the configurations provided. If you think that the behaviour could be improved and/or better documented, feel free to provide suggestions.

Note: See TracTickets for help on using tickets.