226

Is there a way to have the master process log to STDOUT STDERR instead of to a file?

It seems that you can only pass a filepath to the access_log directive:

access_log  /var/log/nginx/access.log

And the same goes for error_log:

error_log /var/log/nginx/error.log

I understand that this simply may not be a feature of nginx, I'd be interested in a concise solution that uses tail, for example. It is preferable though that it comes from the master process though because I am running nginx in the foreground.

Ankur Loriya
  • 3,276
  • 8
  • 31
  • 58
quinn
  • 5,508
  • 10
  • 34
  • 54
  • 19
    Using Nginx inside a Docker container? Checkout [this answer](http://serverfault.com/a/634296/54393). – czerasz Jan 30 '16 at 21:34
  • 1
    The accepted answer (Patrick's) works for official Nginx Docker images (hub.docker.com/_/nginx). – Farshid T May 12 '18 at 10:51

8 Answers8

305

Edit: it seems nginx now supports error_log stderr; as mentioned in Anon's answer.

You can send the logs to /dev/stdout. In nginx.conf:

daemon off;
error_log /dev/stdout info;

http {
  access_log /dev/stdout;
  ...
}

edit: May need to run ln -sf /proc/self/fd /dev/ if using running certain docker containers, then use /dev/fd/1 or /dev/fd/2

Community
  • 1
  • 1
Patrick
  • 5,714
  • 4
  • 31
  • 36
  • 3
    When I try to do this I get the following error: 2014/07/29 10:19:09 [emerg] 13742#0: open() "/dev/stdout" failed (13: Permission denied) – Jon Tirsen Jul 29 '14 at 10:19
  • 1
    Jon, what system are you on? On my system, /dev/stdout is world-readable symlink to /dev/fd/1 which is owned and read+writeable by my user. – Patrick Jul 29 '14 at 19:06
  • Ubuntu 12.04. It seems the problem was that I was using runit chpst to change the user. This means stdout is owned by root and then changed to run as the nginx user. – Jon Tirsen Sep 02 '14 at 13:51
  • 2
    I'm seeing this fail with `ENXIO` when stdout is open to a socket rather than a file. There's an upstream kernel ticket indicating that this is deliberate and by intent: https://bugzilla.kernel.org/show_bug.cgi?id=1360 -- thus, while this answer is sufficient in some cases, it doesn't fully cover the range of possible failures. – Charles Duffy Oct 21 '14 at 22:53
  • 2
    Lost a few hours on this without any success. Tried to change everything (daemon modes, users, nginx versions etc). It just does not work for me. """open() "/dev/stderr" failed (6: No such device or address)""" (same issues with stdout, but nginx should output to `stderr` according to docs) – Ivan Kleshnin Feb 08 '15 at 10:09
  • I've done this in my dockerfile but it's doesn't work `RUN ln -sf /proc/self/fd /dev/` `RUN sed -i 's/access_log.*/access_log \/dev\/fd\/1;/g' /etc/nginx/nginx.conf && sed -i 's/error_log.*/error_log \/dev\/fd\/2 info;/g' /etc/nginx/nginx.conf` – kondor Mar 04 '15 at 15:14
  • 1
    Inside a docker you may get permission denied if your process doesn't run as root in the container. There's a fix coming for this in the next version. – Dobes Vandermeer Oct 23 '15 at 19:37
  • I have an nginx container that doesn't run as `root`, and this answer does not solve that case. Still looking for solution. – peedee Dec 14 '18 at 09:58
  • did anyone find a solution. my nginx server desider not to run without any edits, it just decided to shut down .. wtf – samayo Sep 26 '19 at 21:21
  • 2
    Do not use `/dev/sdtout` or `/dev/stderr`. Use `stdout` or `stderr`. – ErikE Sep 22 '20 at 00:04
  • @ErikE works beautifully, please put it in an answer, so it's more visible, one would need to dig into this thread comments to find the ultimate answer – Omar May 08 '23 at 16:50
  • Do we have any way to get this working in the windows Nginx console, I tried using 'con' but no luck so far. – Abhishek-M Jun 13 '23 at 08:13
  • This answer doesn't work on Windows... I'm trying to get the stdout to log to the console without the stderr. And I don't want to combine the 2 with `2>&1`. – Studocwho Aug 31 '23 at 15:40
91

If the question is docker related... the official nginx docker images do this by making softlinks towards stdout/stderr

RUN ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log

REF: https://microbadger.com/images/nginx

Boeboe
  • 2,070
  • 1
  • 17
  • 21
  • 13
    This answer is mostly correct, but sadly not for the *alpine* images (see https://github.com/nginxinc/docker-nginx/blob/master/stable/alpine/Dockerfile), only for the others like [jessie](https://github.com/nginxinc/docker-nginx/blob/8921999083def7ba43a06fabd5f80e4406651353/mainline/jessie/Dockerfile#L21-L23) do use this statement. If you´re an alpine user, just create your own Dockerfile with `FROM nginx:alpine RUN ln -sf /dev/stdout /var/log/nginx/access.log \ && ln -sf /dev/stderr /var/log/nginx/error.log CMD ["nginx-debug", "-g", "daemon off;"]` – jonashackt Mar 15 '18 at 07:51
  • 2
    Patrick's answer works for official nginx images (https://hub.docker.com/_/nginx/), both debian (latest) and alpine bases. – Farshid T May 12 '18 at 10:49
  • Your REF link appears to be dead. – peedee Dec 14 '18 at 09:55
  • 1
    @jonashackt I used alpine images and I found it also logged to stdout – Qiulang May 14 '19 at 10:00
  • Click on a version (https://hub.docker.com/_/nginx) to see the docker file with the aforementioned line (somewhere before line 100). – qräbnö Dec 20 '19 at 18:27
  • 2
    @jonashackt New versions of alpine do work now https://github.com/nginxinc/docker-nginx/blob/master/stable/alpine/Dockerfile#L109 – ch271828n Jan 31 '21 at 01:54
34
Syntax: error_log file | stderr | syslog:server=address[,parameter=value] | memory:size [debug | info | notice | warn | error | crit | alert | emerg];
Default:    
error_log logs/error.log error;
Context:    main, http, stream, server, location

http://nginx.org/en/docs/ngx_core_module.html#error_log

Don't use: /dev/stderr This will break your setup if you're going to use systemd-nspawn.

timiTao
  • 1,417
  • 3
  • 20
  • 34
Anon
  • 341
  • 3
  • 2
12

For a debug purpose:

/usr/sbin/nginx -g "daemon off;error_log /dev/stdout debug;"

For a classic purpose

/usr/sbin/nginx -g "daemon off;error_log /dev/stdout info;"

Require

Under the server bracket on the config file

access_log /dev/stdout;
intika
  • 8,448
  • 5
  • 36
  • 55
7

When running Nginx in a Docker container, be aware that a volume mounted over the log dir defeats the purpose of creating a softlink between the log files and stdout/stderr in your Dockerfile, as described in @Boeboe 's answer.

In that case you can either create the softlink in your entrypoint (executed after volumes are mounted) or not use a volume at all (e.g. when logs are already collected by a central logging system).

Community
  • 1
  • 1
veuncent
  • 1,599
  • 1
  • 20
  • 17
5

In docker image of PHP-FPM, i've see such approach:

# cat /usr/local/etc/php-fpm.d/docker.conf
[global]
error_log = /proc/self/fd/2

[www]
; if we send this to /proc/self/fd/1, it never appears
access.log = /proc/self/fd/2
Oleg Neumyvakin
  • 9,706
  • 3
  • 58
  • 62
5

Based on the official docker Nginx image this is already in place

For more information you can see the Dockerfile written for the 1-alpine version which soft link the access logs and error logs to the stdout and stderr respectively. Other docker tags also have it.

ref: https://github.com/nginxinc/docker-nginx/blob/1.23.1/stable/alpine/Dockerfile#L118-L119

Kasir Barati
  • 606
  • 13
  • 24
0
# nginx.conf

worker_processes auto;

events {
    worker_connections 4096;
}

error_log  /var/log/nginx/error.log  error;
error_log  /dev/stderr  error;

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    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;
    access_log  /dev/stdout  main;

    #...
    include /etc/nginx/conf.d/*.conf;
}

geekyouth
  • 121
  • 8