Comparing PID's in bash
I'm trying to something very simple and I'm having lots of trouble with it.
I've got a bash script that I have to write for class that performs a function similar to pstree. It reports pstree for itself. The output should look like:
PID
|
PPID
|
.
.
.
|
1
Here is my code so far:
ps -ef>tmp1.txt #save ps -ef to a file
pid=$$
echo $pid #print first PID
while [ $pid != "1" ]
do
cat tmp1.txt | while read line #read in ps -ef file line by line
do
tmp=$(echo $line | cut -f2 -d' ') #return only the PID column of ps -ef
if [$pid == $tmp] #compare current PID to temp PID of current line
then
echo "|"
pid=$(echo $line | cut -f3 -d' ') #if they're the same we found the PPID, so save it
echo $pid #and echo it
fi
done
done
Where it's failing is at the comparison statement:
if [$pid == $tmp]
I get a not found error. Got any ideas why the comparison isn't working? Thanks for any hel开发者_如何转开发p in advance and if I can clarify anything please tell me.
A single equals sign is used to compare strings (if [ $pid = $tmp ]
).
I've edited your question to indent the code. It's much, much easier to read when you indent each while and if statement.
The line you're complaining about is
if [$pid == $tmp]
That's invalid for a couple of reasons already pointed out. Unlike other programming languages, BASH uses a single equals sign, and you must keep a blank space around the square brackets. The square bracket is a command, and must be white space separated. It's an alias for the test
command. This line should look like this:
if [ $pid = $tmp ]
Now, =
is a string comparison, if you're doing a numeric comparison, you should use -eq
instead:
if [ $pid -eq $tmp ]
And, since [
is an alias to the test
command, it could be written like this (but rarely is):
if test $pid -eq $tmp
However, it does show you why you need a space around the square braces.
Your code is not efficient. Try with awk, without temporary file and nested loop:
ps -eo pid,ppid | awk -v START=$$ '
{ PPID[$1]=$2 } # (for each line) create PPIDs table record
END { if (PPID[START]) { # (when done) if starting pid is correct
for(pid=START; pid!=1; pid=PPID[pid]) # print the tree
printf "%d\n|\n", pid;
print 1;
}
}'
For those of you interested my final code looks like this:
echo $pid
while [ $pid != "1" ]
do
while read line
do
tmp="$(echo $line | cut -f2 -d' ')"
if [ $pid = $tmp ];
then
pid="$(echo $line | cut -f3 -d' ')"
fi
done<./tmp1.txt
echo "|"
echo $pid
done
Thanks to all of you jedi masters out there.
精彩评论