I am investigating something. I have a /bin/sh (it is dash in this case) process which runs a script fed into shell's STDIN. Something else launches (daemonizes) this process and I would like to know what this process does and what that script looks like.

For example, if you submit the following into the shell

echo 'echo ONE; sleep 99; sleep 666; echo TWO' | /bin/sh

in the process list at any point in time you can only see the command being executed at the moment (e.g. sleep 99) but not the whole script.

How can I recover the contents of the whole script?

P.S. The focus of this question is not to find a way to tell who/what launches the script or why I need it, etc.

  • is your /bin/sh Bash or something else? (See what /bin/sh --version prints?)
    – ilkkachu
    Oct 23, 2023 at 15:03
  • Assuming you can't get in the "middle" of where the shell is launched (to do something like adding -x to the command line), you could try setting the ENV or BASH_ENV envvars to point to some script (assuming your sh reads those on all invocations), or if nothing else, replace /bin/sh with something that copies the output to stdout too. Though that would be a rather invasive operation for the rest of the system too, but at least on Linux, you could alleviate that by using mount namespaces to do a private mount over /bin/sh for that process only
    – ilkkachu
    Oct 23, 2023 at 15:07
  • Just to clarify; You wrote: Something else launches this process ...; You don't know what is this "something else"? Is that what you want to find out? Is it something that runs periodically? A cron, or system service or something? Is this sh processes running all the time in the background, or it just runs as one-off shots?
    – aviro
    Oct 23, 2023 at 16:26

2 Answers 2


On Linux, you could use bpftrace to report what sh processes read from stdin:

#! /usr/bin/env bpftrace
tracepoint:syscalls:sys_enter_read /comm == "sh"/ {
   * Upon read(2) syscall entry, record whether the read() is on fd 0 (stdin)
   * and if yes, where the read goes on a per-task basis
  @from_stdin[tid] = (args->fd == 0);
  if (@from_stdin[tid]) {
    @addr[tid] = args->buf;
tracepoint:syscalls:sys_exit_read /
  comm == "sh" &&
  @from_stdin[tid] &&
  args->ret > 0
/ {
    "sh process %d read %d bytes from stdin: \"%r\"\n",
                                               buf(@addr[tid], args->ret)

Then running echo 'echo foo | cat' | sh will show in the output of that bpftrace script:

$ sudo ./that-bpftrace-script
./that-script:13:16-18: WARNING: Addrspace mismatch
  comm == "sh" &&
Attaching 2 probes...
sh process 83359 read 15 bytes from stdin: "echo foo | cat\x0a"

(I don't know what the Addrspace mismatch warning is about but it seems harmless; you can suppress it along with the Attaching 2 probes... with -q --no-warning).

  • This is great. How would I trigger the tracing, just by executing the 1st bpftrace script? How would I stop the tracing? Sorry, I had never dealt with bpftrace before. Oct 31, 2023 at 4:19
  • @oᴉɹǝɥɔ, you just run that bpftrace script as root, and then wait for that sh command to be run. Ctrl+C to stop the bpftrace script. Oct 31, 2023 at 6:45

You could try hijacking the shell but this is fraught with potential complications, and most importantly perhaps I have not tested this at all well.

  1. Move the shell from /bin/sh to /bin/sh.bin
  2. Create a script called /bin/sh that captures stdin to a file and then invokes /bin/sh.bin to run it
  3. Remember to ensure the script is executable and that it uses /bin/sh.bin

The script might look something like this


# If it looks interactive run the real shell directly
[ -t 0 ] && exec /bin/sh.bin "$@"

# Otherwise grab stdin and then execute it
tee /tmp/sh_stdin.$$ | /bin/sh.bin "$@"

Make sure you have a different shell open in a root window somewhere. For example, sudo bash, and do not close that session until you have either confirmed that the script hackery works and that you have reverted the changes.

  • This seems like a viable approach Oct 24, 2023 at 4:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .