I am writing a bash script to perform some analysis using the program ROOT. I want to run some initial command to load the result of the analysis, then continue using ROOT interactively.

The analysis part goes along well but the problem is that after root is executes my initial command, it closes immediately. So far I have tried the EOF (here-file) construct to pass my initial command and I am a bit unfamiliar with shell scripting so I would like to get your opinions on how to keep ROOT running after the execution of the script. That is I would like to see the ROOT prompt instead of the sytem prompt.

./runReader.py SummerStd 140PU_NM1 
root -l SummerStd_140PU_NM1_his.root << EOF
TBrowser a;

The above code executes the analysis then runs root; however, it immediately terminates and I have no time to inspect the TBrowser since I have the system prompt instead of the ROOT prompt. I would like control to stay at root's command prompt after the script sends the TBrowser command to the program, so I can enter additional commands by hand.

  • How are you running this script? From a terminal? Or do you click on it in some file manager? Or something else? – Gilles Aug 2 '14 at 22:08
  • @Gilles I run it through zsh from a terminal while logged in a remote terminal. – Vesnog Aug 3 '14 at 22:00
  • It's difficult to tell because you don't describe your whole problem. If the problem is that ROOT dies when you disconnect from the remote machine, then use screen or tmux: see unix.stackexchange.com/questions/131897/… I'm closing this question as a duplicate. If this isn't what you meant, edit your question to clarify it and we can reopen it. – Gilles Aug 3 '14 at 23:55
  • @Gilles Where did he say he was disconnecting from the remote system? – Barmar Aug 4 '14 at 16:00
  • I think I now understand what he wants. ROOT is an interactive program with a command-line interface, and he wants the script to enter the first command into it, then revert to allowing him to type subsequent commands. I think the answer to this is to use Expect. I'm not going to revise my answer, because I don't have enough experience with Expect to show how to do it. – Barmar Aug 4 '14 at 16:02

You could do:

expect -c 'spawn -noecho root -l SummerStd_140PU_NM1_his.root
           send "TBrowser a;\r"
  • Should I write this directly inside the bash script? – Vesnog Aug 5 '14 at 15:42
  • @Vesnog, Yes, in place of your root -l SummerStd_140PU_NM1_his.root << EOF... – Stéphane Chazelas Aug 5 '14 at 15:51
  • expect: not found it fails to find a command expect – MycrofD Nov 27 '17 at 23:55

With ROOT, this is actually easy. Once the root program has read the files passed on the command line, it continues to read interactive commands (unless you pass the -q option). So you can pass your startup commands in an additional file parameter, via an extra file descriptor.

./runReader.py SummerStd 140PU_NM1 
root -l SummerStd_140PU_NM1_his.root /dev/fd/3 3<<'EOF'
TBrowser a;

This is the best approach on Linux, FreeBSD and OSX, but root seems to ignore files that it sees as having a length of 0, so it might not work on some other unix variants where /dev/fd is not a regular file such as Solaris (/dev/fd is a device file) or AIX and HP-UX (/dev/fd doesn't exist). If you need to run your script on these platforms, you can put your startup command in a temporary file¹. The trap command sets up rm -f "$tmp_root" to run when the script exits.

./runReader.py SummerStd 140PU_NM1
trap 'rm -f "$tmp.root"' EXIT HUP INT TERM
cat >tmp_root <<'EOF'
TBrowser a;
root -l SummerStd_140PU_NM1_his.root tmp.root

¹ I'm not using mktemp because it isn't available on some of the “exotic” (i.e. not Linux or *BSD) platforms that you'd use this script on.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.