arut / nginx-rtmp-module

NGINX-based Media Streaming Server
http://nginx-rtmp.blogspot.com
BSD 2-Clause "Simplified" License
13.46k stars 3.52k forks source link

Cannot get stdout and stderr from exec_publish and exec_publish_done #1465

Open BrightSoul opened 4 years ago

BrightSoul commented 4 years ago

Hello, I'm running nginx-rtmp in a docker container. When I run this command on the host machine:

docker logs mycontainer -f

I can see output from nginx-rtmp just fine. Lines like this appear.

172.17.0.1 [06/Dec/2019:12:47:41 +0100] PUBLISH "appname" "streamname" "" - 517328 529 "" "FMLE/3.0 (compatible; FMSc/1.0)" (10s)

Now, I've added the on_publish and on_publish_done directives to the app, like this.

exec_publish /bin/sh /var/scripts/myscript.sh;
exec_publish_done /bin/sh /var/scripts/myscript.sh

However, the output produced by myscript.sh (both on stdout and stderr) does not appear when I run the aforementioned command docker logs mycontainer -f.

Why is this? I tried to be more explicit by using the following configuration, but it didn't help either.

exec_publish /bin/sh /var/scripts/myscript.sh 1>>/dev/stdout 2>>/dev/stderr;
exec_publish_done /bin/sh /var/scripts/myscript.sh 1>>/dev/stdout 2>>/dev/stderr;

It works only when I redirect the output to a file but this is NOT what I want because that ouput would be lost forever when the docker container is restarted.

#Not what I want, it has to go to /dev/stdout and /dev/stderr
exec_publish /bin/sh /var/scripts/myscript.sh 1>>/tmp/file 2>>/tmp/file;
exec_publish_done /bin/sh /var/scripts/myscript.sh 1>>/tmp/file 2>>/tmp/file;
joeflateau commented 4 years ago

@BrightSoul did you find any solution to this?

BrightSoul commented 4 years ago

@BrightSoul did you find any solution to this?

No, unfortunately I'm still waiting for a solution.

In the meantime my requirements changed and I had to do some modifications: instead of executing the script directly, I made a web request to localhost by using the curl command. e.g.

exec_publish curl http://localhost:8080/execute-script;

I then mapped the /execute-script path to fastcgi like this.

location /execute-script {
  fastcgi_param SCRIPT_FILENAME /var/scripts/myscript.sh;
  include fastcgi_params;
  fastcgi_param PATH_INFO $1;
  fastcgi_pass unix:/run/fcgi.sock;
}

Where /run/fcgi.sock is the path to a unix socket which fcgiwrap is listening on. fcgiwrap is launched and managed by Supervisor with the following configuration.

[fcgi-program:fcgi]
command=/usr/bin/fcgiwrap
socket=unix:///run/fcgi.sock
numprocs=5
process_name=%(program_name)s_%(process_num)02d
directory=/tmp
autostart=true
autorestart=true
startretries=3
exitcodes=0
stopsignal=QUIT
stopasgroup=false
killasgroup=false
stopwaitsecs=10
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
serverurl=AUTO

Now I'm looking for a way to make nginx log response bodies or headers, preferrably when the status code is != 200.

joeflateau commented 4 years ago

Interesting... what I'm trying is using named pipes/fifo to bring it all together.

dockerfile:

RUN mkdir /pipes && \
    mkfifo /pipes/stdout && \
    mkfifo /pipes/stderr

RUN ln -sf /pipes/stdout /usr/local/nginx/logs/access.log && \
    ln -sf /pipes/stderr /usr/local/nginx/logs/error.log

nginx.sh

nginx &
nginxpid=$!;

cat /pipes/stdout &
stdoutcatpid=$!;

cat /pipes/stderr 1>&2 &
stderrcatpid=$!;

cleanup(){
    kill -TERM "$nginxpid"
    kill -TERM "$stdoutcatpid"
    kill -TERM "$stderrcatpid"
}

trap cleanup TERM

wait

nginx.conf

                        exec_push /var/transcode/transcode.sh $name
                            >>/pipes/stdout
                            2>>/pipes/stderr;
joeflateau commented 4 years ago

I'll probably use supervisord instead of this nginx.sh and find a way to prefix log lines to differentiate what is logging, but I do get all of the console output this way