LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 01-31-2018, 04:55 PM   #1
pedropt
Member
 
Registered: Aug 2014
Distribution: Devuan
Posts: 345

Rep: Reputation: Disabled
Unable to identify an error on a loop using kill


Hi , i am building a script that will check if from a list of http links if they are online .

since i am using a list , then i am using a loop for this , every time the script does a loop it reads the next line from a file (containing the urls) , then get that url , executes wget to get that file from url , then after 5 seconds of downloading kills wget process .
After this point it goes check the incomplete downloaded file for its size , if size is near 0 then it says that link is down , else it says that link is ok .

during all this process the script removes from a temp folder the pid file that it got when wget was starting and it removes the incompleted downloaded file so it can start all over again to the next line of the url file list .

The script is very simple , but somehow during the process i get an error saying that the pid from wget was already terminated !!! , i have no idea why i get this message in the end of the loop , because that pid was killed a few lines before and i an not killing it again .

It looks complicated but it is not , however i am unable to write here a simple practical example but just some part of the code i am using , and a screenshot from terminal .

I will explain line by line what the script does , so you have an idea how it is working .
Code:
# this line gets from a specific file all the urls starting in "http"
# and removes from the captured urls the ones that have png of jpg

glnk=$(grep -F "http" < "$path/temp/1" | sed '/jpg/d' | sed '/png/d')

# this line writes all the desired urls to a new file

echo "$glnk" | tr " " "\n" > "$path/temp/2"

# this line counts all the urls to be checked so i can setup a loop
srvnmb=$(wc -l "$path/temp/2" | awk '{print$1}')

# these both lines remove any temporary temp files
rm -rf "$path/temp/stream" >/dev/null 2>&1
rm -rf "$path/temp/pid.tmp" >/dev/null 2>&1

# loop start from 1 to the number from variable srvnmb
for i in $(seq "$srvnmb")
do

#this line reads the line number in i
chkf=$(sed -n "${i}p" < "$path/temp/2")

#this line reads the first 4 letters from the previous line
chkurl=$(echo "$chkf" | head -c 4)

# here it checks if it is an url http or a rtmp
case "$chkurl" in
http|rtmp|HTTP)

rm -rf "$path/temp/stream" >/dev/null 2>&1
rm -rf "$path/temp/pid.tmp" >/dev/null 2>&1

#here starts wget , that will get the file from that url and
# at same time the script will create a pid file with wget pid to  #kill later
wget "$chkf" -O "$path/temp/stream" >/dev/null 2>&1 & echo $! > "$path/temp/pid.tmp" 

# here i read the current pid from wget to a variable
pid=$(sed -n 1p < "$path/temp/pid.tmp")

# this timer is to wait for wget to retrieve some data from url
sleep 5

# on this line i check if wget pid is still active
rpid=$(ps -p "$pid" -o pid= | awk '{print$1}')

# in case the pid is active then kill it
if [[ "$rpid" == "$pid" ]]
then
kill "$pid" > /dev/null 2>&1
fi

# this if cause i check if the downloaded file exists
if [[ ! -f "$path/temp/stream" ]]
then
echo "Error reading captured file"
else

# on this line i check the size in bytes from the downloaded file
stsz=$(wc -c "$path/temp/stream" | awk '{print$1}')

# if the size of the file is less that 100 bytes  then url is down
if [[ "$stsz" -le "100" ]]
then
echo "$chkf is down"
else
echo "$chkf is ok"
fi
fi
;;

# this next case option is in case the url does not starts with http
#this way i can bypass any error in wget 
*)
;;
esac
done

after this point the loop starts all over again
The next image is from my terminal running the script , it says line 21 but line 21 in script is where the "case" sentence starts , and have nothing to do with this error .

https://s14.postimg.org/fg1c2bq4x/iptv-check_031.jpg

I remember to had this error in some scripts before , but i never knew the reason for this to happen .

Does anyone have a slight idea ?

Last note : It is interesting that if the link is down then the error does not appear , despite the fact that a 0 bytes file is created , but if link is ok then these errors start to appear .
The difference between them is that one file have size , and other not , but both exists .
But the error is not even on checking the output file , but with the killing process that i called to check somehow !??? , and then i get those wget calls without the variables previous readed .

I even try to put some helpers on the code to identify the error , but everything is ok .
By example i placed an echo to print the variable that wget will check after this code :

case "$chkurl" in
http|rtmp|HTTP)
echo "$chkf"

and everything is fine .
However , i believe that one of the causes of this issue is that wget may be not outside of execution memory when next call is given to it , but i am not sure .

If until tomorrow no one had a clue why this is happening because it may have some difficulty to test the code , then i will try to build a simple test script based on this one for all of you test there .

Last edited by pedropt; 01-31-2018 at 06:14 PM.
 
Old 01-31-2018, 06:14 PM   #2
keefaz
LQ Guru
 
Registered: Mar 2004
Distribution: Slackware
Posts: 6,552

Rep: Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872
It's not an error, it looks like the standard message that bash outputs on stderr when a background job has finished
 
Old 01-31-2018, 06:15 PM   #3
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (15 current), Slack15, Ubuntu studio, MX Linux, FreeBSD 13.1, WIn10
Posts: 10,342

Rep: Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242
check to see if file exist is
Code:
if [[ -e $path/temp/stream ]] ; then
rm -rf "$path/temp/stream" >/dev/null 2>&1
fi

if [[ -e $path/temp/pid.tmp ]] ; then
rm -rf "$path/temp/pid.tmp" >/dev/null 2>&1
fi
-f is used to compare between a file and a directory to be sure it is a file and not a directory. that can be combined into one 'if condition && condition then' statement as well.


condensing your code.
Code:
                #var name goes here
  [[ "$(wc -c  windowmaker.stuff | awk '{print$1}')" -le '100' ]]  && echo "less" || echo "more"
needs to be transformed into an if else statement because Bash has no real trinary operator, or use that at your discretion.


I would remove you rm statements and rewrite them in lower in your code.
Code:
# in case the pid is active then kill it
if [[ "$rpid" == "$pid" ]]
then
#kill pid
kill "$pid" > /dev/null 2>&1
[check] then get rid of file here
fi


#i'd rewrite this
if [[ ! -e "$path/temp/stream" ]]
then
echo "file not present, something went wrong, oops!"
echo "check with developer for reasons why"
else

# on this line i check the size in bytes from the downloaded file
# if the size of the file is less that 100 bytes  then url is down
if [[ "$(wc -c  windowmaker.stuff | awk '{print$1}')" -le '100' ]]
then
echo "$chkf is down"
else
echo "$chkf is ok"
fi
[check] then remove stream file here.
fi
to this
Code:
#if file present
if [[ -e "$path/temp/stream" ]] ;
then #then get size
	if [[ "$(wc -c  windowmaker.stuff | awk '{print$1}')" -le '100' ]] ;
	then
	{
	   echo "$chkf is down"
	   #remove file here
	}
	else
	{
	  echo "$chkf is ok"
	  #remove file here
	}
	fi
else
   echo "file not present, something went wrong, oops!"
   echo "check with developer for reasons why"
fi
then see what that does for you by getting rid of the files after you've used them and not before.

Last edited by BW-userx; 01-31-2018 at 06:38 PM.
 
Old 01-31-2018, 07:21 PM   #4
pedropt
Member
 
Registered: Aug 2014
Distribution: Devuan
Posts: 345

Original Poster
Rep: Reputation: Disabled
Thank you both , i belive that keefaz hit the spot on this one .
https://unix.stackexchange.com/quest...-a-bash-script


I will check this tommorow and i make some tests .
 
Old 01-31-2018, 07:27 PM   #5
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (15 current), Slack15, Ubuntu studio, MX Linux, FreeBSD 13.1, WIn10
Posts: 10,342

Rep: Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242
Quote:
Originally Posted by pedropt View Post
Thank you both , i belive that keefaz hit the spot on this one .
https://unix.stackexchange.com/quest...-a-bash-script


I will check this tommorow and i make some tests .
yeah I didn't catch the image part after I posted I seen his and then your image and yes I agree, never the less you do have -f to do what?

this is how I deal with a pid but it is not using a file
Code:
#kill the prior pids leaving the new one
function killoldPid(){
# add the script name <script name> remove the < > brackets also, when adding the what ever you named this script
if [ $(pgrep -u $USER setbg | wc -l) -ge 2 ] && [ $(pgrep -u $USER sleep | wc -l ) -ge 1 ]; then
	echo $(pgrep -u $USER setbg | wc -l) "pid# --" $(pgrep -u $USER sleep | wc -l)
	pkill -u $USER -o sleep
	pkill -u $USER -o setbg # <--you need to add what you call this script here <script-name>
else
         # add script name here too 
        echo "setbg pid $(pgrep -u $USER setbg ) sleep pid $(pgrep -u $USER sleep)"
fi

}

Last edited by BW-userx; 01-31-2018 at 07:35 PM.
 
Old 01-31-2018, 08:57 PM   #6
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,011

Rep: Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194
I'm wondering if it is a bit over complicated? Obviously the below is untested, but you probably get the idea:
Code:
  no_img='(jpg|png)'
  
  while read -r line
  do
    [[ "$line" =~ http && ! "$line" =~ $no_img ]] || continue
  
    wget -qT5 "$line" -O "$path/temp/stream"
  
    if [[ -s "$path/temp/stream" ]]
    then
      echo "$line is ok"
    else
      echo "$line is down"
    fi  
  
    rm "$path/temp/stream"
done<"$path/temp/1"
 
Old 02-01-2018, 01:44 AM   #7
pedropt
Member
 
Registered: Aug 2014
Distribution: Devuan
Posts: 345

Original Poster
Rep: Reputation: Disabled
Code:
#kill the prior pids leaving the new one
function killoldPid(){
# add the script name <script name> remove the < > brackets also, when adding the what ever you named this script
if [ $(pgrep -u $USER setbg | wc -l) -ge 2 ] && [ $(pgrep -u $USER sleep | wc -l ) -ge 1 ]; then
	echo $(pgrep -u $USER setbg | wc -l) "pid# --" $(pgrep -u $USER sleep | wc -l)
	pkill -u $USER -o sleep
	pkill -u $USER -o setbg # <--you need to add what you call this script here <script-name>
else
         # add script name here too 
        echo "setbg pid $(pgrep -u $USER setbg ) sleep pid $(pgrep -u $USER sleep)"
fi

}
i was unable to understand this code cound you give me a functional example ?
as name of the script running , we can get it by declaring a variable as :

Code:
sctname=$0 #this will get current script name only no matter its name could be
 
Old 02-01-2018, 02:13 AM   #8
pedropt
Member
 
Registered: Aug 2014
Distribution: Devuan
Posts: 345

Original Poster
Rep: Reputation: Disabled
Here is is a quick script to test yourselves in there .

create a file name with this code :

Code:
#!/bin/bash
path=$(pwd)
sname=$0
echo "script name running is $sname"
echo ""
srvnmb=$(wc -l "$path/1" | awk '{print$1}')
rm -rf "$path/stream*" >/dev/null 2>&1
rm -rf "$path/pid.tmp" >/dev/null 2>&1
for i in $(seq "$srvnmb")
do
chkf=$(sed -n "${i}p" < "$path/1")
chkurl=$(echo "$chkf" | head -c 4)
case "$chkurl" in
http|rtmp|HTTP)
echo "Variable is $chkf"
wget -q "$chkf" -O "$path/stream" & echo $! > "$path/pid.tmp" 
pid=$(sed -n 1p < "$path/pid.tmp")
sleep 4 
rpid=$(ps -p "$pid" -o pid= | awk '{print$1}')
if [[ "$rpid" == "$pid" ]]
then
kill $pid >/dev/null 2>&1
fi
if [[ ! -f "$path/stream" ]]
then
echo "Error reading captured file"
else
stsz=$(wc -c "$path/stream" | awk '{print$1}')
if [[ "$stsz" -le "100" ]]
then
echo "$chkf is down"
else
echo "$chkf is ok"
fi
fi
;;
*)
;;
esac
rm -rf "$path/stream" >/dev/null 2>&1
rm -rf "$path/pid.tmp" >/dev/null 2>&1
done
Now create on same folder another file called "1" with this data :

run the script just by writing "./test"

Based on this simple script could you give me a functional example to hide the stderr messages from current bash script ?

Last edited by pedropt; 02-01-2018 at 02:58 AM.
 
Old 02-01-2018, 04:28 AM   #9
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,011

Rep: Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194
Can you not just run the script as:
Code:
./test 2>/dev/null
 
Old 02-01-2018, 07:03 AM   #10
pedropt
Member
 
Registered: Aug 2014
Distribution: Devuan
Posts: 345

Original Poster
Rep: Reputation: Disabled
nop , it is not practical , specially because this is a script to go to github .
Eventually based on your reply i may find a proper solution more practical , like when the script starts will check if there is another process with same name running , case exists then will restart itself with that command .
But i have to figure out how will i do it .
 
Old 02-01-2018, 07:15 AM   #11
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,976

Rep: Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337
wget -q "$chkf" -O "$path/stream" && echo $! > "$path/pid.tmp"
here probably an & is missing
 
Old 02-01-2018, 08:09 AM   #12
pedropt
Member
 
Registered: Aug 2014
Distribution: Devuan
Posts: 345

Original Poster
Rep: Reputation: Disabled
Quote:
wget -q "$chkf" -O "$path/stream" && echo $! > "$path/pid.tmp"
nop , it is exactly as i want it .
 
Old 02-01-2018, 08:23 AM   #13
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,976

Rep: Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337
I'm not really sure about that. If you want to send it to background you need to take care about the messages too, otherwise you will get the messages about the completed tasks. From the other hand & is usually the last char on the line (in case it is a single &), but anyway it is just unusual, not syntactically incorrect.
If you want to handle those background processes you need to use wait.
 
Old 02-01-2018, 08:26 AM   #14
pedropt
Member
 
Registered: Aug 2014
Distribution: Devuan
Posts: 345

Original Poster
Rep: Reputation: Disabled
just found a solution .

Code:
sname=$0
if [[ ! -f "$path/null" ]]
then
echo "0" > "$path/null"
exec $sname $1 2>/dev/null
exit 1
fi
rm -rf "$path/null" >/dev/null 2>&1
continue the script .....
basically , the user just need to start the script normally , the script will check if file "null" exists in its directory , in case does not exist then it will create that file , will launch itself again with the stderr suppressed .

On relaunch it will delete that null file for the next start .

Looks complicated but it is not

Last edited by pedropt; 02-01-2018 at 08:28 AM.
 
Old 02-01-2018, 08:29 AM   #15
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,976

Rep: Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337
you can suppress strerr completely by:
Code:
exec 2>/dev/null
 
  


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
Unable to kill process with kill -9 pgb205 Linux - Software 5 01-13-2011 03:55 PM
Unable to identify tty name error on new install fbsduser Slackware 4 10-04-2010 09:34 PM
Unable to mount loop filesystem error with PCLinuxOS Pr9.1 sc123 Linux - Software 1 09-19-2008 11:08 AM
one line identify and kill PID (scriptable) r00tb33r Linux - Software 3 02-06-2008 04:52 PM
Webmin error - unable to identify operating system LittleAngel Linux - Software 2 05-15-2004 04:21 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 06:30 PM.

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