ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Now I'm trying to write a mini-script that uses a -p option with a ProcessID as an argument. Example:
Code:
[prompt]$ ./findpid -p 123456
Process not found!
[prompt]$ echo $?
1
[prompt]$ ./findpid -p 1111
root 1111 0.0 0.0 1392 372 tty6 S Mar17 0:00 /sbin/foo
[prompt]$ echo $?
0
I've got a script that does that, and it works. The only thing is, its not handling regular expressions properly. The regexp in the grep command I'm using is saying:
"from the beginning of the line, match any number of upper or lowercase characters, followed by any number of spaces, and return the number after those spaces, followed by a space"
See the output of me running the script above or below if that didnt make sense. I'm trying to capture the 2nd field of a ps aux command, the Process ID. The script needs to read in regular expressions as well as hard-coded PID's. So far only the hard-coded values work properly in the script, passing regular expressions, even simple ones causes unexpected output, and I can't see why:
Code:
#!/bin/bash2
declare PID_Input
declare Command_Return_Value
while getopts p: arguments 2>/dev/null
do
case $arguments in
p) PID_Input=$OPTARG;;
\?) echo "Usage: pidinput [ -p PID ]"; exit 1;;
esac
done
# See if the $PID_Input matches a process ID from a ps aux command
ps aux | grep -q "^[A-Za-z].* .*$PID_Input "
CommandReturnValue=$?
if [ "$CommandReturnValue" == "1" ]; then # if grep did not find PID
echo "Process not found!"
exit 1
fi
# Still here? Ok, re-run ps aux | grep without the -q (quiet) flag,
# we want to see the output this time.
ps aux | grep "^[A-Za-z].* .*$PID_Input "
I want to be able to handle regular expressions as input, like so:
Code:
[prompt]$ ./findpid -p 1..1
root 1011 0.0 0.0 88 372 ? S Mar17 0:00 /sbin/foo
root 1101 0.5 0.3 1511 372 ? S Mar17 0:00 /sbin/lowpro2k3
root 1111 0.0 0.0 1392 372 tty6 S Mar17 0:00 /sbin/foo
user 1411 0.2 2.6 1112 372 ? S Mar17 0:00 /home/barbin
mysql 1551 0.1 0.4 11392 72 tty3 S Mar17 0:00 /usr/local/foo
root 1691 0.4 0.1 420 372 ? S Mar17 0:00 /sbin/foo
[prompt]$ echo $?
0
[prompt]$ ./findpid -p [1-4]
root 1 0.0 0.0 1416 456 ? S Mar17 0:04 init
root 2 0.0 0.0 0 456 ? S Mar17 0:00 [keventd]
root 3 0.0 0.0 0 456 ? S Mar17 0:00 [kmapd]
root 4 0.0 0.0 0 456 ? S Mar17 0:00 [ksoftirqd_CPU0]
[prompt]$ echo $?
0
[prompt]$ ./findpid -p 1234[5-6][6-7]78[0-3]0
Process not found!
[prompt]$ echo $?
0
I found a fix for it. It seems like some people looked at this question, so I might as well post what the problem was in case anyone searches for a bash question in the future.
I don't fully understand the logic here, but the regular expression I used was slightly off. I wrapped the open word \< and close word \> brackets around the input variable to make sure it was a word being searched. When I was using regular expressions such as dot or question mark operators, I was sometimes picking up spaces following the process ID. Heres the old expression that didnt work:
Code:
ps aux | grep "^[A-Za-z].* .*$PID_Input "
and here's the correct one (notice open word/close word surrounding $PID_Input
Code:
ps aux | grep "^[A-Za-z].* .*\<$PID_Input\> "
and the fixed script
Code:
#!/bin/bash2
declare PID_Input
declare Command_Return_Value
while getopts p: arguments 2>/dev/null
do
case $arguments in
p) PID_Input=$OPTARG;;
\?) echo "Usage: pidinput [ -p PID ]"; exit 1;;
esac
done
# See if the $PID_Input matches a process ID from a ps aux command
ps aux | grep -q "^[A-Za-z].* .*\<$PID_Input\> "
CommandReturnValue=$?
if [ "$CommandReturnValue" == "1" ]; then # if grep did not find PID
echo "Process not found!"
exit 1
fi
# Still here? Ok, re-run ps aux | grep without the -q (quiet) flag,
# we want to see the output this time.
ps aux | grep "^[A-Za-z].* .*\<$PID_Input\> "
I'm just starting to learn Awk right now (well yesterday/2 days ago). I have another assignment due tonite in Awk, and I'm having a bit of difficulty with it (came here to post a question, check it out if its in the next 3 hours).
ps aux | awk '{ print $2 }'
is alot easier than
ps aux | grep "^[A-Za-z].* .*$PID_Input "
I know that now I think our teacher wants us to do things the hard way before the easy way, so we appreciate the easy way
Originally posted by mrGenixus care to attach complete script file with name and info so other people can use it. Also: where did you find your information
I'm sure theres better ways, but for my first 'real' bash/sh script I think its pretty darn OK
bam
ps+
Code:
#!/bin/bash
declare -i cmdResult=0
function psController()
{
# First thing done is a check to see if there's anything to
# output. Running grep with a -q flag runs it in 'quiet'
# mode. I do this, searching if the $USER_INPUT matches
# a username. After the command, the return value of grep
# is set in the cmdResult variable. If the user doesn't exist
# or have any processes running, a msg is displayed and
# the script exits
ps aux | grep -q "^\<$USER_INPUT\> "
cmdResult=$?
if [ "$cmdResult" == "1" ] && [ "$USER_INPUT" != "" ]
then
echo "User not found!"
exit 1
fi
# Here I basically do the same thing as above, but this time I
# do a quiet grep search to see if the Process ID exists. If it
# doesn't, an error message is displayed, and the script exits
ps aux | grep -q "^[A-Za-z0-9].* .*\<$PID_INPUT\> .*[0-9].*\.[0-9].* "
cmdResult=$?
if [ "$cmdResult" == "1" ] && [ "$PID_INPUT" != "" ]
then
echo "Process not found!"
exit 1
fi
# Display the formatted table row, before calling any functions to
# output data.
displayTableHeader
# If the -u flag and an argument were passed to the script,
# and there is users that match the argument, call the
# showUserProcesses function
if [ "$USER_INPUT" != "" ]
then
showUserProcesses
fi
# This does the same as above, but calls the Process ID
# function instead
if [ "$PID_INPUT" != "" ]
then
showProcessID
fi
# If the -c flag was set when running the script, call the
# function which displays processes with non-zero CPU usage
if [ "$NONZERO_FLAG" = "1" ]
then
showNonZeroCPU
fi
}
function showUserProcesses()
{
# match -u argument from ps aux output with a regular expression
ps aux | grep "^\<$USER_INPUT\> "
}
function showProcessID()
{
# match -p argument from ps aux output with a regular expression
ps aux | grep "^[A-Za-z0-9].* .*\<$PID_INPUT\> .*[0-9].*\.[0-9].* "
}
function showNonZeroCPU()
{
# show processes with a non-zero CPU usage
ps aux | grep -v "^[A-Za-z0-9].* .*[0-9].* .*\<0.0\>" | grep -v "^USER .*"
}
function displayTableHeader
{
printf "%-11s%-4s%-5s%-7s%-5s%-4s%-9s%-5s%-8s%-5s%-25s\n" \
"USER" "PID" "%CPU" "%MEM" "VSZ" "RSS" \
"TTY" "STAT" "START" "TIME" "COMMAND"
}
function exitError()
{
# Display usage when someone enters wrong command-line options
echo "Usage: ps+ [ -u username ] [ -p PID ] [ -c ]"
exit 1
}
declare USER_INPUT="" # User string to search for - cmd-line argument of -u
declare PID_INPUT="" # Process ID to search for - cmd-line argument of -p
declare NONZERO_FLAG=0 # Set to 1 if -c flag is set at the command-line
# This while loop parses the command-line arguments, using the
# getopts function. Both -u and -p must be followed by arguments,
# and the -c flag should be sent to the script without arguments.
# Error messages from getopts are redirected to /dev/null
while getopts u:p:c arguments 2>/dev/null
do
# Start case selection statement for command-line arguments
case $arguments in
# The user entered -u as an argument, we must search by user_id.
# This case statement makes sure that users don't enter -u more
# than once, if -u is entered more than once control is sent
# to an error function and the script exits with return value of 1
# Make sure that -u flag is only passed once
u) if [ "$USER_INPUT" = "" ]
then
# Set USER_INPUT to the argument of -u
USER_INPUT=$OPTARG
else
# Exit script if -u was entered twice
exitError
fi;;
# Make sure that -p flag is only passed once
p) if [ "$PID_INPUT" = "" ]
then
# Set PID_INPUT to the argument of -p
PID_INPUT=$OPTARG
else
# Exit script if -p was entered twice
exitError
fi;;
# Set NONZERO_FLAG to 1 if the -c option was
# given at the command line
c) NONZERO_FLAG=1;;
# Exit script if any other options were passed
\?) exitError;;
esac
done
# If no command line options were passed to the script, exit quietly
if [ "$USER_INPUT" = "" ] &&
[ "$PID_INPUT" = "" ] &&
[ $NONZERO_FLAG = 0 ]
then
exit 1
fi
# Call function psController to take control of output
psController
It used to be in 2 files, (ps+ and ps+fns) and I used to source ps+fns into ps+. I just copied/pasted all the functions at the top, if you want to see how it works, skip all the functions first and jump right to the "while getopts..." line, thats basically where I start my 'main() function'.
Other than that, hopefully someone can get some sort of use from this, I sure spent a long time on it
I saw it at the beginning of the semester and scoffed at it, thinking that one book couldnt possibly cover grep, sed, awk, bash, tcsh, korn, bourne, and lots more, but its become my #1 most used book over the past few weeks. It might be more helpful to me because my curriculum if fairly built around this book, but I seriously say that its a pretty good book. The bash chapters dont assume you read the previous korn shell chapters, and theres a CD with textfiles to manipulate (their small, and also printed in the book if your lazy like me and dont want to hunt the CD for one file )
I would recommend it to someone who wants to learn a bit more about regexp's and alot more about shell programming.
I'll post my "man page" (written in MS word for assignment submission )
I forgot my original question was for a simpler 'piece' of my script. The script I posted above is the complete version, you can perform the following operations:
* search for processes owned by a particular user
* search for a process by a particular process ID
* display processes with non-zero CPU usage
You use command-line flags to achieve these results
-u username
-p PID
-c
If anyones interested in using it (dont see why you would, but who knows), and assuming your using windows, its probably easiest to copy what I posted, paste it into notepad/wordpad/text editor, save it as ps+ (no file extension) and ftp/scp it to your linux computer.
Then when you want to use it, heres a few examples of how:
Code:
[prompt]$ ./ps+
Nothing displays
[prompt]$ ./ps+ -u root
Displays all processes owned by root
[prompt]$ ./ps+ -p 1234
Displays process with PID of 1234 or "Process not found!" message
[prompt]$ ./ps+ -c
Displays all processes with non-zero cpu usage
Yes, you can combine flags, but it doesnt work as you would expect. First users with name $USER will appear (ie - root), then processes, then non-zero processes. I didnt have time to get it working 'properly'
Heres the "man page"
Code:
NAME
ps+ - display processes based on input criteria
SYNOPSIS
ps+ [ -u USERNAME ] [ -p PROCESS ID ] [ -c ]
DESCRIPTION
Display information about PROCESSES being executed. No data is displayed if –upc are missing.
-u USERNAME
Display processes owned by USERNAME
-p PROCESS ID
Display processes with PID of PROCESS ID
-c
Display processes with non-zero CPU usage
AUTHOR
Program written by <lowpro2k3>, program requirements written by <lowpro2k3's teacher>
REPORTING BUGS
Report bugs to
<fp.unit@gmail.com> or
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.