6

Running a php-fpm application in a Docker container based on CentOS7.

Since I am using Docker I have to write my log output from all processes to PID 1's output. This way the Docker engine can snag the logs for later processing (so they show in docker logs).

I can accomplish this by writing ALL logs to /proc/1/fd/2 without issue in any application. I can do it with nginx and just doing echo "test" > /proc/1/fd/2 and it shows up fine for docker logs.

However with php software I would like to do the same thing, write to /proc/1/fd/2 however no matter what I do, I cannot seem to get the file stream going for it.

PHP-FPM spawns many child processes. Because of this I have to explicitly write to stdout for PID 1!

So I am doing something like this:

$handle = fopen("/proc/1/fd/2", "w");
fwrite($handle, $msg);
fclose($handle);

I just get Warning: fopen(/proc/1/fd/2): failed to open stream: No such file or directory

NOTE: I have also tried this with https://www.php.net/manual/en/function.file-put-contents.php and the same result happens. It's essentially a wrapper for fopen, fwrite, fclose.

I tried throwing it at a symlink:

bash-4.2$ ls -l /tmp/stdout
lrwxrwxrwx. 1 nginx nginx 12 Apr 10 11:19 /tmp/stdout -> /proc/1/fd/2

and then pointing the method to it like fopen("/tmp/stdout", "w");

I get the exact same error Warning: fopen(/tmp/stdout): failed to open stream: No such file or directory

Here is the output I need to write to:

bash-4.2$ ls -l /proc/1/fd/2
l-wx------. 1 nginx nginx 64 Apr 10 11:21 /proc/1/fd/2 -> pipe:[3523867]

I can write to it without issue (either directly or through a symlink) using any other application I've tried, including nginx and bash.

THE PHP PROCESS IS RUNNING AS THE SAME USER THAT OWNS THE OUTPUT STREAM

bash-4.2$ ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
nginx        1     0  0 11:21 ?        00:00:00 php-fpm: master process (/etc/php-fpm.conf)
nginx        7     1  0 11:21 ?        00:00:00 php-fpm: pool www
nginx        8     1  0 11:21 ?        00:00:00 php-fpm: pool www
nginx        9     1  0 11:21 ?        00:00:00 php-fpm: pool www
nginx       10     1  0 11:21 ?        00:00:00 php-fpm: pool www
nginx       11     1  0 11:21 ?        00:00:00 php-fpm: pool www
nginx       12     1  0 11:21 ?        00:00:00 php-fpm: pool www

bash-4.2$ ls -l /proc/1/fd/2
l-wx------. 1 nginx nginx 64 Apr 10 11:21 /proc/1/fd/2 -> pipe:[3523867]

I tried throwing some wild permissions at it, they don't take:

bash-4.2$ chmod 777 /proc/1/fd/2
bash-4.2$ ls -l /proc/1/fd/2
l-wx------. 1 nginx nginx 64 Apr 10 11:21 /proc/1/fd/2 -> pipe:[3523867]

Here is the /dev/ directory, I cannot use these since they point to proc/self not /proc/1:

lrwxrwxrwx. 1 root root   11 Apr 10 11:21 core -> /proc/kcore
lrwxrwxrwx. 1 root root   13 Apr 10 11:21 fd -> /proc/self/fd
crw-rw-rw-. 1 root root 1, 7 Apr 10 11:21 full
drwxrwxrwt. 2 root root   40 Apr 10 11:21 mqueue
crw-rw-rw-. 1 root root 1, 3 Apr 10 11:21 null
lrwxrwxrwx. 1 root root    8 Apr 10 11:21 ptmx -> pts/ptmx
drwxr-xr-x. 2 root root    0 Apr 10 11:21 pts
crw-rw-rw-. 1 root root 1, 8 Apr 10 11:21 random
drwxrwxrwt. 2 root root   40 Apr 10 11:21 shm
lrwxrwxrwx. 1 root root   15 Apr 10 11:21 stderr -> /proc/self/fd/2
lrwxrwxrwx. 1 root root   15 Apr 10 11:21 stdin -> /proc/self/fd/0
lrwxrwxrwx. 1 root root   15 Apr 10 11:21 stdout -> /proc/self/fd/1

I tried changing /dev/fd symlink to point to /proc/1/fd/2 and then trying to write to php://fd/2 and it also didn't work, same error.

emmdee
  • 1,541
  • 3
  • 25
  • 46
  • Messing around in `/proc` is not the way to do this. Instead find a way to aggregate logging through some other method. Consider creating a logger process with a socket you can write to. – tadman Apr 10 '19 at 18:38
  • @tadman https://serverfault.com/questions/658367/how-to-get-php-fpm-to-log-to-stdout-stderr-when-running-in-a-docker-container I'm just using the widely accepted method here. – emmdee Apr 10 '19 at 20:14
  • That might work, but it's also going to result in some seriously messed up logging output if multiple processes write to the same filehandle directly. The output from each process will be mixed together pretty badly unless each process explicitly flushes output after each newline, and even then I'm not sure it'll be okay. – tadman Apr 10 '19 at 21:06
  • @emmdee Did you find any answer to your issue? – TeChn4K Mar 10 '23 at 09:45

3 Answers3

0

php-fpm is running under the nginx user, and i bet the nginx user does not have access to /proc/1/fd/2

to see how far the nginx user can go, run:

sudo -u nginx /bin/sh -c 'namei -l /proc/1/fd/2'

i bet it won't reach 2, and namei will tell you where the error occurs, fix your permissions.

for the record, when i run this on a Debian Linux system, i get:

root@x2ratma:~# sudo -u www-data /bin/sh -c 'namei -l /proc/1/fd/2'
f: /proc/1/fd/2
drwxr-xr-x root root /
dr-xr-xr-x root root proc
dr-xr-xr-x root root 1
dr-x------ root root fd
                     2 - Permission denied

telling me that the www-data user does not have READ access to the /proc/1/fd folder. (a dirty quickfix to that would be: sudo chmod a+rx /proc/1/fd which means give everybody read access to /proc/1/fd )

hanshenrik
  • 19,904
  • 4
  • 43
  • 89
0

I solve this by setting error_log to /proc/1/fd/2 in php.ini, and used error_log to send the log to PHP's system logger.

error_log($msg, 0);
Diblo Dk
  • 585
  • 10
  • 26
-1

I'm facing the same issue. For now, as a workaround I will try a background "tail -f" on the real log file and redirect the output from tail to /proc/1/fd/1, something like this:

tail -f file.log > /proc/1/fd/1 &

Not the best solution, but it could get the job done

Nelson Garcia
  • 144
  • 1
  • 7