4

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;
EOF

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.

Vesnog
  • 679
  • 4
  • 11
  • 29
  • How are you running this script? From a terminal? Or do you click on it in some file manager? Or something else? – Gilles 'SO- stop being evil' Aug 02 '14 at 22:08
  • @Gilles I run it through zsh from a terminal while logged in a remote terminal. – Vesnog Aug 03 '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 http://unix.stackexchange.com/questions/131897/keeping-a-process-running-on-server-even-ssh-is-closed 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 'SO- stop being evil' Aug 03 '14 at 23:55
  • @Gilles Where did he say he was disconnecting from the remote system? – Barmar Aug 04 '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 04 '14 at 16:02
  • @Barmar Well Barmer thanks that is exactly what I want so you suggest me to look into the keyword Expect. – Vesnog Aug 04 '14 at 21:05
  • @Vesnog If you go to StackOverflow you can find a number of examples of what you want under the expect tag. – Barmar Aug 04 '14 at 21:39
  • @Gilles I only require ROOT run as long as I am logged in. My point is that ROOT closes when the execution of the shell script finishes; I would like to have ROOT prompt in front of me with TBrowser open and ready for user input. I hope it is clear now. – Vesnog Aug 05 '14 at 09:50
  • ROOT does not close because the execution of the shell script finishes, it's the opposite: the shell script waits for ROOT to exit. I think that you want to keep ROOT running after it executes the TBrowser command and to be able to type more commands at ROOT's prompt, did I understand your question correctly? – Gilles 'SO- stop being evil' Aug 05 '14 at 12:21
  • @Gilles Definitely that is what I want. Do you have any ideas? – Vesnog Aug 05 '14 at 15:41

2 Answers2

3

You could do:

expect -c 'spawn -noecho root -l SummerStd_140PU_NM1_his.root
           send "TBrowser a;\r"
           interact'
1

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.

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

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.

#!/bin/sh
./runReader.py SummerStd 140PU_NM1
tmp_root=tmp-$$.root
trap 'rm -f "$tmp.root"' EXIT HUP INT TERM
cat >tmp_root <<'EOF'
TBrowser a;
EOF
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.