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
  • 239
  • 1
  • 10
  • 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.

Stephen Harris
  • 42,369
  • 5
  • 94
  • 123
  • 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 &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