0

I want to do a bash script with these requirements:

REQUIREMENTS:

The script:

  • launches, in parallel, the execution of several processes
  • waits for the processes to finish execution before continuing its own execution.

Each process:

  • takes a relative long time to finish execution

  • should output its logs to both a child gnome-terminal window and to a log file, which should be different from the terminal windows and log files of the other processes and the terminal window used by the father script.

  • should not finish even if the user closed the corresponding child gnome-terminal window. That means it should keep on running and outputing logs to its corresponding log file even if the user either closed the child gnome-terminal window or pressed ctrl+c on the child gnome-terminal window.

MY TRY:

I have tried to implement this with the code below:

nohup gnome-terminal --wait -- bash -c "cd /home;find . -name "foo*" | tee /home/$USER/log-home.txt" &
nohup gnome-terminal --wait -- bash -c "cd /home/$USER; find . -name "foo*" | tee /home/$USER/log-$USER.txt" &
wait;
echo "Finished";

The code abgove does not meet the expected requirements though:

  • If I close a child gnome-terminal window, the process running within it stops outputing logs to the corresponding log file. I guess this process just finishes running.
  • If I close all the child gnome-terminal windows launched from the father script, the father script continues running the script lines after the wait command.
goahead97
  • 65
  • 8
  • A standalone process is called a daemon. See https://stackoverflow.com/q/17954432/1216776 on reqs for creating. – stark Feb 18 '23 at 14:12
  • if you want the bash to continue, why are you applying nohup to the terminal? – jhnc Feb 18 '23 at 17:22
  • I just thought using nohup would help to achieve this: the process run in each child gnome-terminal window will not stop even if I close the mentioned child terminal. – goahead97 Feb 18 '23 at 18:20
  • Another try: ```gnome-terminal --wait -- bash -c "cd /home;find . -name \"foo*\" 2>&1 | tee /home/$USER/log-home.txt & wait" & gnome-terminal --wait -- bash -c "cd /home/$USER;find . -name \"foo*\" 2>&1 | tee /home/$USER/log-$USER.txt & wait" & wait echo "Finished"``` Problem of this: if user closes both child gnome-terminal windows manually before their corresponding process finishes, then the father script keeps waiting. – goahead97 Feb 19 '23 at 11:22

1 Answers1

0

This is a stab at trying to accomplish what you identified. The logic flow should be as required, but when executing, it is behaving "flaky", meaning that the windows are "dying", but only after initially persisting. I can't see what is killing processes which are expected to run indefinitely. Maybe someone more expert can spot what I am missing.

So, here is the script:

#!/bin/bash

logdir="$(pwd)"

seconds=6
others=$((seconds+=1))
matchCommand="sleep ${seconds}"

terminal="gnome-terminal"
terminal="mate-terminal"


jobOne="${logdir}/job1.sh"
cat >"${jobOne}" <<EnDoFiNpUt
while true
do
    date
    ${matchCommand}
done > ${logdir}/Output.txt
EnDoFiNpUt
chmod 750 "${jobOne}"

jobTwo="${logdir}/job2.sh"
cat >"${jobTwo}" <<EnDoFiNpUt
while true
do
    date
    ${matchCommand}
done > ${logdir}/WORKS.txt
EnDoFiNpUt
chmod 750 "${jobTwo}"


actionOne="${logdir}/action1.sh"
cat >"${actionOne}" <<EnDoFiNpUt
echo 'waiting ${others} sec to execute ...'
sleep ${others}
cd ${logdir}/Output
nohup ${jobOne} &
RC_loop=\$?
echo "Process ID for loop = \${RC_loop} ..."
sleep ${others} ; tail -f ${logdir}/Output.txt | awk -v cmd=\`basename \$0 \` '{ printf("%s| %s\n", cmd, \$0 ) ; }' &
RC_tail=\$?
echo "Process ID for tail = \${RC_tail} ..."
while true
do
    sleep ${others}
    testor=\`ps -e | awk -v procID=\"\${RC_loop}\" '{ if( \$1 == procID ){ print \$0 } ; }' \`
    if [ -z "\${testor}" ]
    then
        kill -9 \${RC_tail}
        break
    fi
    echo -e "\t Process \${RC_loop} is still running ..."
done
echo -e "\n Hit return to close window ..." ; read k
EnDoFiNpUt
chmod 750 "${actionOne}"

actionTwo="${logdir}/action2.sh"
cat >"${actionTwo}" <<EnDoFiNpUt
echo 'waiting ${others} sec to execute ...'
sleep ${others}
cd ${logdir}/WORKS
nohup ${jobTwo} &
RC_loop=\$?
echo "Process ID for loop = \${RC_loop} ..."
sleep ${others} ; tail -f ${logdir}/WORKS.txt | awk -v cmd=\`basename \$0 \` '{ printf("%s| %s\n", cmd, \$0 ) ; }' &
RC_tail=\$?
echo "Process ID for tail = \${RC_tail} ..."
while true
do
    sleep ${others}
    testor=\`ps -e | awk -v procID=\"\${RC_loop}\" '{ if( \$1 == procID ){ print \$0 } ; }' \`
    if [ -z "\${testor}" ]
    then
        kill -9 \${RC_tail}
        break
    fi
    echo -e "\t Process \${RC_loop} is still running ..."
done
echo -e "\n Hit return to close window ..." ; read k
EnDoFiNpUt
chmod 750 "${actionTwo}"


shell_command="bash"

${terminal} --execute ${shell_command} -c "${actionOne}" &
${terminal} --execute ${shell_command} -c "${actionTwo}" &


PIDs=""

for PID in `ps -ef |
    grep "${matchCommand}" |
    grep -v grep |
    awk -v com="${shell_command}" '{ if( $8 == com ){ print $3 } ; }' `
do
    PIDs="${PIDs} ${PID}"
done

sleep 4
if [ -n "${PIDs}" ] ; then  ps -ef ${PIDs} ; fi
ls -ld ${logdir}/Output.txt
ls -ld ${logdir}/WORKS.txt

if [ -n "${PIDs}" ] ; then  wait ${PIDs} ; fi
echo "Finished";
Eric Marceau
  • 1,601
  • 1
  • 8
  • 11