LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software
User Name
Password
Linux - Software This forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.

Notices


Reply
  Search this Thread
Old 12-13-2019, 08:18 AM   #1
taylorkh
Senior Member
 
Registered: Jul 2006
Location: North Carolina
Distribution: CentOS 6, CentOS 7 (with Mate), Ubuntu 16.04 Mate
Posts: 2,127

Rep: Reputation: 174Reputation: 174
Timing a running process in bash script - having my cake and eating it too :-)


I need to call a process from a script. It may or may not complete in a reasonable amount of time. I would like to be able to "start the clock" on the process and then, if the process completes I would examine the return code and move on. If I reach my timeout limit I would take other actions. Here is a test script which I have written in an attempt to figure this out
Code:
#!/bin/bash

function my_function {

declare -i j=0

while [ $j -lt 5 ]
do
  echo hello
  j=$j+1

done
sleep 5
echo 
return 27
}


SECONDS=0
running=0
elapsedseconds=0
while [ $elapsedseconds -lt 10 ]
do
  if [ $running -eq 0 ]
  then
    running=1
    my_function
  else
    sleep 1
  fi
   elapsedseconds=$SECONDS
   echo $elapsedseconds
done

echo "time is up!"
echo $?
In this case "my_function" will launch and control will NOT return to the script until my_function completes. If I change the script to execute my_function& control returns to the calling script but I loose the return code from my_function. With my_function& and setting the sleep in the function to 15 illustrates part of what I wish to achieve.

In my actual script my_function will call an external script and I could, using my typical big hammer programming approach, simply wait for a reasonable time and the check to see if the process has completed satisfactorily. If not I will kill the process with my big hammer and move on to take remedial action. That would get the job done but it is rather crude. Any suggestions?

TIA,

Ken

p.s. Bonus question

Why do I have to declare j as an integer lest I get an error "integer expression expected" while I do NOT have to declare elapsedseconds?
 
Old 12-13-2019, 08:39 AM   #2
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,830

Rep: Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308
there is a command timeout (see man page) to limit execution time and there is a command time (as bash builtin and external command too) to measure execution time. You do not need to [re]implement.

Quote:
Originally Posted by taylorkh View Post
Why do I have to declare j as an integer lest I get an error "integer expression expected" while I do NOT have to declare elapsedseconds?
Because you made an arithmetic operation with that variable.
Probably would be better to use (( )) for that.
 
Old 12-13-2019, 08:58 AM   #3
taylorkh
Senior Member
 
Registered: Jul 2006
Location: North Carolina
Distribution: CentOS 6, CentOS 7 (with Mate), Ubuntu 16.04 Mate
Posts: 2,127

Original Poster
Rep: Reputation: 174Reputation: 174
Thank you pan64,

Let me see if I can take advantage of timeout.

I see the error about "j". I changed j=$J+1 to ((j=$J+1)) and I no longer need to declare it as an integer.

Ken
 
Old 12-13-2019, 01:35 PM   #4
teckk
LQ Guru
 
Registered: Oct 2004
Distribution: Arch
Posts: 5,137
Blog Entries: 6

Rep: Reputation: 1826Reputation: 1826Reputation: 1826Reputation: 1826Reputation: 1826Reputation: 1826Reputation: 1826Reputation: 1826Reputation: 1826Reputation: 1826Reputation: 1826
j=$(($j + 1))

Code:
j=0
while [ $j -lt 5 ]; do
  echo "$j"
  j=$(($j + 1))
done
Code:
my_function() {
    sleep 1000 & #simulate long process
    p=$! #get pid
    for j in {0..4}; do
        echo "Running for "$((++j))" seconds."
        sleep 1
    done
echo "time is up, killing pid "$p""
kill "$p"
}
 
Old 12-13-2019, 05:52 PM   #5
taylorkh
Senior Member
 
Registered: Jul 2006
Location: North Carolina
Distribution: CentOS 6, CentOS 7 (with Mate), Ubuntu 16.04 Mate
Posts: 2,127

Original Poster
Rep: Reputation: 174Reputation: 174
Thanks teckk,

I do not need to kill the long running process. What I wish to do is:

1 - start the VPN connection process
2 - hope for the best
3 - wait for perhaps 30 seconds
4 - check to see if the VPN is connected
5 - based on what I see in the log take some remedial action
6 - try again to start the VPN

I have seen cases where the connection process stalls and never returns. Thus I need to run the clock in parallel with the connection process. On the other hand I do not want to check immediately after initiating the connection process. It needs time to work.

On third thought perhaps I will fire it off, sleep 30 and then begin checking. I have gotten myself confused in where and how I want to divide control logic and timing between my functions and the main script. Time for some pencil and paper I think.

Ken
 
Old 12-14-2019, 04:32 AM   #6
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,830

Rep: Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308
you may need to use background processes.
You can also check this (or similar pages): https://stackoverflow.com/questions/...imeout-in-bash
 
1 members found this post helpful.
Old 12-14-2019, 06:03 AM   #7
ondoho
LQ Addict
 
Registered: Dec 2013
Posts: 19,872
Blog Entries: 12

Rep: Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053
Recent bash versions have an environment variable called SECONDS that contains exactly that - for how many seconds the script has been running.
So instead of defining your own SECONDS you could/should just use that, no?
 
Old 12-14-2019, 09:01 AM   #8
teckk
LQ Guru
 
Registered: Oct 2004
Distribution: Arch
Posts: 5,137
Blog Entries: 6

Rep: Reputation: 1826Reputation: 1826Reputation: 1826Reputation: 1826Reputation: 1826Reputation: 1826Reputation: 1826Reputation: 1826Reputation: 1826Reputation: 1826Reputation: 1826
I did not know about that, thanks.
Code:
echo $SECONDS
The length of time the shell has been open.

So one could open something in a sub shell and time it.
Code:
time (
for i in {1..5}; do 
    echo "$i"
    sleep 1
done
)

1
2
3
4
5

real    0m5.008s
user    0m0.004s
sys     0m0.003s
Or in a shell
Code:
funct() {
SECONDS=0
for i in {1..5}; do
    echo "$i"
    sleep 1
done
echo "Run time "$SECONDS""
}

funct
1
2
3
4
5
Run time 5
 
Old 12-15-2019, 07:28 AM   #9
taylorkh
Senior Member
 
Registered: Jul 2006
Location: North Carolina
Distribution: CentOS 6, CentOS 7 (with Mate), Ubuntu 16.04 Mate
Posts: 2,127

Original Poster
Rep: Reputation: 174Reputation: 174
Thanks pan64,

I have been playing around with that. Looking at your reply again caused an idea to pop into mind. I write log entries from the various parts of my script. I might be able to launch the connection process in background and then have a loop in them main scrip which will periodically tail the log to look for a successful VPN connection. Better yet, what I have been working on yesterday, are some state variables which show if the VPN is connected and what sort of connection I want (no connection, a specific exit server, a random connection server from a preferred list or just the "fastest" server based on latency.) I could simply check one of those variables which would be adjusted by the connection function (if a background process can change a variable initialized in the calling script - need to check that.)

Thanks ondoho and teckk,

I have played around with SECONDS. As I described above I do not really need to know how long the connection process took. Rather I need to know when it completed or if it is taking too long I need to take remedial action. This script is definitely sufferomg from scope creep

Ken
 
Old 12-15-2019, 09:14 AM   #10
taylorkh
Senior Member
 
Registered: Jul 2006
Location: North Carolina
Distribution: CentOS 6, CentOS 7 (with Mate), Ubuntu 16.04 Mate
Posts: 2,127

Original Poster
Rep: Reputation: 174Reputation: 174
Thanks to all the contributors to this thread. I think I have got it figured out now. Here are my test scripts. First my function which will reside in a separate file (two.sh in this test case) with a bunch more functions
Code:
#!/bin/bash
# this function will be called to connect the VPN
function something {

# start by disconnecting any current connection - also seems to clear a failed connection
echo `date` " Disconnecting VPN" >> /var/log/protonvpn.log	
pvpn -d  | tee -a /var/log/protonvpn.log

# now make the fresh connection
echo `date` " Connecting fastest VPN server" >> /var/log/protonvpn.log	
pvpn --cc US  | tee -a /var/log/protonvpn.log

# let us see what we are conected to
pvpn --status | tee -a /var/log/protonvpn.log

return
}
And then the calling script
Code:
#!/bin/bash
# bring in the various functions needed by the script (only 1 in this test case)
source two.sh

# vpnon is used for state tracking in the real script
vpnon=0
j=0

# call the function to connect the VPN
something&

# keen an eye on the log to see when (if) the VPN connects
while [ $j -le 60 ]
do

if  tail /var/log/protonvpn.log | grep "Connected!" > /dev/null
then
  j=61
  vpnon=1
fi
  (( j = $j +1 ))
  echo "j = " $j
  echo "vpnon = " $vpnon
  sleep 1
done

if [ $vpnon -eq 1 ]
then
  echo "VPN connected successfully"
else
  echo "VPN connection failed :-(  need to fix it"
fi
I have tested this process under various scenarios and it seems to work as desired. In addition, I observed the mysterious "[!] Error: There is an internet connection issue." error which sometimes hoses my current connection script. I think I will look for it in the log file from within the same loop rather than after the connection process completes. I will set a state variable to hold that information so that after the 60 second allotted time I can cycle the network connections on the Pi which from experience will fix things. Then the production loop will detect that the VPN is SUPPOSED to be running and that it is NOT running and it will then re-try the connection. I love it when a plan comes together

Ken
 
Old 12-16-2019, 12:42 AM   #11
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,830

Rep: Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308
yes, good news
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
LXer: My Nerd Life: Too Loud, Too Funny, Too Smart, Too Fat LXer Syndicated Linux News 0 01-24-2014 05:21 AM
Help to kill process that is eating too much CPU. jtbinuya Linux - Newbie 7 01-16-2009 01:59 AM
LXer: Have your cake and eat it, too: Adopt open source software LXer Syndicated Linux News 0 12-20-2006 05:21 AM
how to start timing and print the timing result on portions of java codes ?? alred Programming 2 05-15-2006 10:00 AM
I'd like my cake & eat it too please! Log to both console and file ericcarlson Linux - Software 1 03-01-2005 03:07 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software

All times are GMT -5. The time now is 10:07 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration