0

I'm trying to use script as the entrypoint of a docker container to log everything that happens in that container to a file on a mounted volume. It works great if there is a tty:

$ docker run -t --rm --privileged -v $PWD:/log rhel7:7.7 /usr/bin/script /log/out.script --timing=/log/out.timing -f -e -c 'echo "hello world"; sleep 10; echo "goodbye world"'
Last login: Tue Jan 21 00:45:14 UTC 2020 on pts/41
Script started, file is /log/out.script
hello world
goodbye world
Script done, file is /log/out.script

However, if I remove the TTY, script doesn't execute any of the '-c' commands:

$ docker run --rm --privileged -v $PWD:/log rhel7:7.7 /usr/bin/script /log/out.script --timing=/log/out.timing -f -e -c 'echo "hello world"; sleep 10; echo "goodbye world"'
Last login: Tue Jan 21 00:50:39 UTC 2020 on pts/41
Script started, file is /log/out.script
Script done, file is /log/out.script
$ ls -s out.*
0 out.script  0 out.timing

Unfortunately, the environment I plan on running in will not have TTYs for containers. What is reason for script behaving this way? Is there a way around it?

pavon
  • 238
  • I'm no docker specialist, but it looks like it has to do with your particular setup or with the script program you're using: I've tried it with a simple container with just busybox, script and the needed libs, and it works OK with or without -t. –  Jan 21 '20 at 02:34

1 Answers1

1

The script command is designed to capture terminal output. Without a terminal, it just won't work.

You may want to look at the tee command instead:

foo 2>&1 | tee /my/output

Will send the output of foo to the standard docker output and copy it to the specified file.

  • tee was actually my first approach, but it is harder to use when running multiple commands; bash -c 'echo "hello world"; sleep 10; echo "goodbye world" |& tee /log/out.log' only writes "goodby world". So you have to use more nesting/escaping, and it becomes mess. – pavon Jan 21 '20 at 01:22
  • What are you saying makes sense. I was misinterpreting this sentence in the man page: This makes it easy for a script to capture the output of a program that behaves differently when its stdout is not a tty. to mean you were running a shell script without a tty and could use script -c to run commands that expect one. But it was really talking about running a shell script with a tty, but don't want to remove that tty from the child commands by redirecting their output. – pavon Jan 21 '20 at 01:31
  • 1
    This sounds like a case for ptyrun. https://unix.stackexchange.com/a/249801/5132 – JdeBP Jan 21 '20 at 01:50
  • 1
    script is supposed to allocate a pseudo-tty itself; why does it need a tty? Sorry if I don't get what you're trying to say. But: setsid cat /dev/tty => No such device or address (as expected). setsid script /tmp/log -c 'echo yup' => OK (as expected). –  Jan 21 '20 at 02:19
  • @pavon you absolutely CAN run script(1) without a tty: just try it: setsid script /dev/null -c ls </dev/null 2>&1 | cat –  Jan 21 '20 at 02:46
  • I was able to get this working with tee, after realizing that I could start a new shell with parenthesis bash -c '( commands; I; want; to; run) |& tee out.log', which doesn't have the messy quoting/escaping of my original approach using nested bash -c statements. – pavon Jan 21 '20 at 19:04
  • I am still curious about why script isn't working in my situation. I'll play around with it more during my downtime, and leave the question open for a bit before marking it answered. – pavon Jan 21 '20 at 19:07