How to get all process ids without ps command on Linux - linux

How to get all process ids (pid) (similar to: $ ps aux) but without using ps.
One example of when this would be used is when developing a dotnet 5 application to run on a docker host. The dotnet runtime image is a very cut-down Linux image, with bash, but without ps. When diagnosing an issue with the application, it's sometimes useful to see what processes are running and if separate processes have been spawned correctly. ps is unavailable on this image. Is there an alternative?

On Linux, all running process have "metadata" stored in the /proc filesystem.
All running process ids:
shopt -s extglob # assuming bash
(cd /proc && echo +([0-9]))

Further to the comment by #FelixJongleur42, the command
ls -l /proc/*/exe
yields a parseable output with additional info such as the process user, start time and command.

This one-liner will give you the pid and the cmd with args:
for prc in /proc/*/cmdline; { (printf "$prc "; cat -A "$prc") | sed 's/\^#/ /g;s|/proc/||;s|/cmdline||'; echo; }

Based on Ivan's example with some filtering:
for prc in /proc/*/cmdline; {
(printf "$prc "; cat -A "$prc") | sed 's/\^#/ /g;s|/proc/||;s|/cmdline||' | grep java ; echo -n;
}

Related

how to get a complete command of X apps via 'wmctl' and 'ps'?

I'm working on a program that can query running X apps, save all the commands of running apps and them reopen them latter.
I encounter an issue. wmctctl can query the pid of Onlyoffice, for example the pid is 123. Then run ps -ef -q 123, I see that the CMD is ./DesktopEditors which should be a invalid command, because ./one_command only can work in special folder include file one_command.
I can get a complete command by running ps -ef -q $(pgrep -P 123).
Is there a straight way to get the complete command of Onlyoffice just via wmctl and ps?
If there is a better way to get all commands of X apps, please let me know. Thanks.
I suggest using ps -h -e -o pid,args command piped with a grep
This should provide full command path with it arguments and options.
For example find all running java programs with their arguments (might be extensive):
ps -eo pid,args | grep java
In your case I suggest a small awk script, that looks for the pid given as 3rd input field in current line:
wmctrl -l -p|awk '{system("ps -h --pid "$3" -o args")}'
Sample output
nautilus-desktop --force
/usr/libexec/gnome-terminal-server
/usr/libexec/gnome-terminal-server
update
Transforming current directory ./ to to full path.
Assuming ./ represent the current working directory.
Add the following pipe.
wmctrl -l -p|awk '{system("ps -h --pid "$3" -o args")}'|sed "s|^\./|$PWD/|"
Find the script or program DesktopEditors in your computer, using find / -name "DesktopEditors".
But I believe this is useless if you are trying to reverse engineer a web based application that requires some kind of a browser emulator.

How to check if Neo4J is running on the server?

Is there any way to check whether Neo4J is running using pidof command? I tried doing
pidof /path/to/neo4j/bin/neo4j
But it didn't seem to work.
I need it to set up a script that I will then launch with cron to make sure that if the database crashes I can restart it again.
Thank you!
bin/neo4j status is the command you are looking for.
For a more general use, checking whether neo4dj is running or not, use the following command:
service neo4j-service status
In Ubuntu 16 04 I can execute the following:
sudo service neo4j status
That won't work since neo4j is being run by java command.
Here's a workaround if you want to do something by yourself:
if test -z "$(ps -A | grep neo4j)"
then
echo "no neo4j instance running"
else
echo "neo4j up and running"
fi
But since, as you may probably know, noe4j launcher already does something like that, we may just look at how it's done there:
detectrunning() {
if [ $DIST_OS = "solaris" ] ; then
## SmartOS has a different lsof command line arguments
newpid=$(lsof -o $NEO4J_SERVER_PORT | grep '::' | head -n1 | cut -d ' ' -f 1)
else
## This could be achieved with filtering using -sTCP:LISTEN but this option is not available
## on lsof v4.78 which is the one bundled with some distros. So we have to do this grep below
newpid=$(lsof -i :$NEO4J_SERVER_PORT -F T -Ts | grep -i "TST=LISTEN" -B1 | head -n1)
newpid=${newpid:1}
fi
}
This is an excerpt from the bin/neo4j script inside neo4j distribution directory.
You can use these following ways to get neo4j service status in Windows:
Powershell:
Get-Service neo4j
CMD/Powershell:
service neo4j

using sed and pstree to display the type of terminal being used

I've been trying to display the type of terminal being used as the name only. For instance if I was using konsole it would display konsole. So far I've been using this command.
pstree -A -s $$
That outputs this.
systemd---konsole---bash---pstree
I have the following that can extract konsole from that line
pstree -A -s $$ | sed 's/systemd---//g;s/---.*//g' | head -1
and that outputs konsole properly. But some people have output from just the pstree command that can look like this.
systemd---kdeinit4---terminator---bash---pstree
or this
systemd---kdeinit4---lxterminal---bash---pstree
and then when I add the sed command it extracts kdeinit4 instead of terminator. I can think of a couple scenarios to extract the type of terminal but none that don't contain conditional statements to check for specific types of terminals. The problem I'm having is I can't accurately predict how many non or non-relative things may be infront or behind of the terminal name or what they will be nor can I accurately predict what the terminal name will be. Does anyone have any ideas on a solution to this?
You could use
ps -p "$PPID" -o comm=
Or
ps -p "$PPID" -o fname=
If your shell does not have PPID variable set you could get it with
ps -p "$(ps -p "$$" -o ppid= | sed 's|\s\+||')" -o fname=
Another theory is that the parent process of the current shell that doesn't belong to the same tty as the shell could actually be the one that produces the virtual terminal, so we could find it like this as well:
#!/bin/bash
shopt -s extglob
SHELLTTY=$(exec ps -p "$$" -o tty=)
P=$$
while read P < <(exec ps -p "$P" -o ppid=) && [[ $P == +([[:digit:]]) ]]; do
if read T < <(exec ps -p "$P" -o tty=) && [[ $T != "$SHELLTTY" ]]; then
ps -p "$P" -o comm=
break
fi
done
I don't know how to isolate the terminal name on your system, but as a parsing exercise, and assuming the terminal is directly running your bash you could pipe the pstree output through:
awk -F"---bash---" ' NF == 2 { count = split( $1, arr, "---" ); print arr [count]; }'
This will find the word prior to the "---bash---" which in your examples is
konsole
terminator
lxterminal
If you want different shell types, you could expand the field separator to include them like:
awk -F"---(bash|csh)---" ' NF == 2 { count = split( $1, arr, "---" ); print arr[count]; }'
Considering an imaginary line like:
systemd---imaginary---monkey---csh---pstree
the awk would find "monkey" as the terminal name as well as anything from your test set.
No guarantees here, but I think this will work most of the time, on linux:
ps -ocomm= $(lsof -tl /proc/$$/fd/0 | grep -Fxf <(lsof -t /dev/ptmx))
A little explanation is probably in order, but see man ps, man lsof and (especially) man pts for information.
/dev/ptmx is a pseudo-tty master (on modern linux systems, and some other unix(-like) systems). A program will have one of these open if it is a terminal emulator, a telnet/ssh daemon, or some other program which needs a captive terminal (screen, for example). The emulator writes to the pseudo-tty master what it wants to "type", and reads the result from the pseudo-tty slave.
/proc/$$/fd/0 is stdin of process $$ (i.e. the shell in which the command is executed). If stdin has not been redirected, this will be a symlink to some slave pseudotty, /dev/pts/#. That is the other side of the /dev/ptmx device, and consequently all of the programs listed above which have /dev/ptmx open will also have some /dev/pts/# slave open as well. (You might think that you could use /dev/stdin or /dev/fd/0 instead of /proc/$$/fd/0, but those would be opened by lsof itself, and consequently would be its stdin; because of the way lsof is implemented, that won't work.) The -l option to lsof causes it to follow symlinks, so that will cause it to show the process which have the same pts open as the current shell.
The -t option to lsof causes it to produce "terse" output, consisting only of pids, one per line. The -Fx options to grep cause it to match strings, rather than regex, and to force a full line match; the -f FILE option causes it to accept the strings to match from FILE (which in this case is a process substitution), one per line.
Finally, ps -ocomm= prints out the "command" (chopped, by default, to 8 characters) corresponding to a pid.
In short, the command finds a list of terminal emulators and other master similar programs which have a master pseudo-tty, and a list of processes which use the pseudo-tty slave; finds the intersection between the two, and then looks up the command name for whatever results.
curTerm=$(update-alternatives --query x-terminal-emulator | grep '^Best:')
curTerm=${curTerm##*/}
printf "%s\n" "$curTerm"
And the result is
terminator
Of course it can be different.
Now you can use $curTerm variable in your sed command.
But I am not sure if this is going to work properly with symlinks.

Linux command to check if a shell script is running or not

What is the linux command to find if a process say aa.sh is running or not.
ps command does not seem to work and it does not show the shell script names.
Please advise.
Check this
ps aux | grep "aa.sh"
The simplest and efficient solution is :
pgrep -fl aa.sh
Adding to the answers above -
To use in a script, use the following :-
result=`ps aux | grep -i "myscript.sh" | grep -v "grep" | wc -l`
if [ $result -ge 1 ]
then
echo "script is running"
else
echo "script is not running"
fi
Check this
ps -ef | grep shellscripname.sh
You can also find your running process in
ps -ef
The solutions above are great for interactive use, where you can eyeball the result and weed out false positives that way.
False positives can occur if the executable itself happens to match, or any arguments that are not script names match - the likelihood is greater with scripts that have no filename extensions.
Here's a more robust solution for scripting, using a shell function:
getscript() {
pgrep -lf ".[ /]$1( |\$)"
}
Example use:
# List instance(s) of script "aa.sh" that are running.
getscript "aa.sh" # -> (e.g.): 96112 bash /Users/jdoe/aa.sh
# Use in a test:
if getscript "aa.sh" >/dev/null; then
echo RUNNING
fi
Matching is case-sensitive (on macOS, you could add -i to the pgrep call to make it case-insensitive; on Linux, that is not an option.)
The getscript function also works with full or partial paths that include the filename component; partial paths must not start with / and each component specified must be complete. The "fuller" the path specified, the lower the risk of false positives. Caveat: path matching will only work if the script was invoked with a path - this is generally true for scripts in the $PATH that are invoked directly.
Even this function cannot rule out all false positives, as paths can have embedded spaces, yet neither ps nor pgrep reflect the original quoting applied to the command line. All the function guarantees is that any match is not the first token (which is the interpreter), and that it occurs as a separate word, optionally preceded by a path.
Another approach to minimizing the risk of false positives could be to match the executable name (i.e., interpreter, such as bash) as well - assuming it is known; e.g.
# List instance(s) of a running *bash* script.
getbashscript() {
pgrep -lf "(^|/)bash( | .*/)$1( |\$)"
}
If you're willing to make further assumptions - such as script-interpreter paths never containing embedded spaces - the regexes could be made more restrictive and thus further reduce the risk of false positives.
pgrep -f aa.sh
To do something with the id, you pipe it. Here I kill all its child tasks.
pgrep aa.sh | xargs pgrep -P ${} | xargs kill
If you want to execute a command if the process is running do this
pgrep aa.sh && echo Running
I was quite inspired by the last answer by mklement0 - I have few scripts/small programs I run at every reboot via /etc/crontab. I built on his answer and built a login script, which shows if my programs are still running.
I execute this scripts.sh via .profile -file on every login, to get instant notification on each login.
cat scripts.sh
#!/bin/bash
getscript() {
pgrep -lf ".[ /]$1( |\$)"
}
script1=keepalive.sh
script2=logger_v3.py
# test if script 1 is running
if getscript "$script1" >/dev/null; then
echo "$script1" is RUNNING
else
echo "$script1" is NOT running
fi
# test if script 2 is running:
if getscript "$script2" >/dev/null; then
echo "$script2" is RUNNING
else
echo "$script2" is NOT running
fi
here a quick script to test if a shell script is running
#!/bin/sh
scripToTest="your_script_here.sh"
scriptExist=$(pgrep -f "$scripToTest")
[ -z "$scriptExist" ] && echo "$scripToTest : not running" || echo "$scripToTest : runnning"
Give an option to ps to display all the processes, an example is:
ps -A | grep "myshellscript.sh"
Check http://www.cyberciti.biz/faq/show-all-running-processes-in-linux/ for more info
And as Basile Starynkevitch mentioned in the comment pgrep is another solution.

Why are commands executed in backquotes giving me different results when done in as script?

I have a script that I mean to be run from cron that ensures that a daemon that I wrote is working. The contents of the script file are similar to the following:
daemon_pid=`ps -A | grep -c fsdaemon`
echo "daemon_pid: " $daemon_pid
if [ $daemon_pid -eq 0 ]; then
echo "restarting fsdaemon"
/etc/init.d/fsdaemon start
fi
When I execute this script from the command prompt, the line that echoes the value of $daemon_pid is reporting a value of 2. This value is two regardless of whether my daemon is running or not. If, however, I execute the command with back quotes and then examine the $daemon_pid variable, the value of $daemon_pid is now one. I have also tried single stepping through the script using bashdb and, when I examine the variables using that tool, they are what they should be.
My question therefore is: why is there a difference in the behaviour between when the script is executed by the shell versus when the commands in the script are executed manually? I'm sure that there is something very fundamental that I am missing.
You're very likely encountering the grep as part of the 'answer' from ps.
To help fully understand what is happening, turn off the -c option, to see what data is being returned from just ps -A | grep fsdameon.
To solve the issue, some systems have a p(rocess)grep (pgrep). That will work, OR
ps -A | grep -v grep | grep -c fsdaemon
Is a common idiom you will see, but at the expense of another process.
The cleanest solution is,
ps -A | grep -c '[f]sdaemon'
The regular expression syntax should work with all greps, on all systems.
I hope this helps.
The problem is that grep itself shows up... Try running this command with anything after grep -c:
eple:~ erik$ ps -a | grep -c asdfladsf
1
eple:~ erik$ ps -a | grep -c gooblygoolbygookeydookey
1
eple:~ erik$
What does ps -a | grep fsdaemon return? Just look at the processes actually listed... :)
Since this is Linux, why not try the pgrep? This saves you a pipe, and you don't end up with grep reporting back the daemon script itself running.
Aany process with arguments including that name will add to the count - grep, and your script.
psing for a process isn't really reliable, you should use a lock file.
As several people have pointed out already, your process count is inflated because ps | grep detects (1) the script itself and (2) the subprocess created by the backquotes, which inherits the name of the main script. So an easy solution is to change the name of the script to something that doesn't include the name you're looking for. But you can do better.
The "best-practice" solution that I would suggest is to use the facilities provided by your operating system. It's not uncommon for an init script to create a PID file as part of the process of starting your daemon; in other words, instead of just running the daemon itself, you use a wrapper script that starts the daemon and then writes the process ID to a file somewhere. If start-stop-daemon exists on your system (and I think it's fairly common these days), you can use that like so:
start-stop-daemon --start --quiet --background \
--make-pidfile --pidfile /var/run/fsdaemon.pid -- /usr/bin/fsdaemon
(obviously replace the path /usr/bin/fsdaemon as appropriate) to start it, and then
start-stop-daemon --stop --quiet --pidfile /var/run/fsdaemon.pid
to stop it. start-stop-daemon has other options that might be useful to you, which you can investigate by reading the man page.
If you don't have access to start-stop-daemon, you can write a wrapper script to do basically the same thing, something like this to start:
echo "$$" > /var/run/fsdaemon.pid
exec /usr/bin/fsdaemon
and this to stop:
kill $(< /var/run/fsdaemon/pid)
rm /var/run/fsdaemon.pid
(this is pretty crude, of course, but it should normally work).
Anyway, once you have the setup to generate a PID file, whether by using start-stop-daemon or not, you can update your check script to this:
daemon_pid=`ps --no-headers --pid $(< /var/run/fsdaemon.pid) | wc -l`
if [ $daemon_pid -eq 0 ]; then
echo "restarting fsdaemon"
/etc/init.d/fsdaemon restart
fi
(one would think there would be a concise command to check whether a given PID is running, but I don't know it).
If you don't want to (or can't) create a PID file, I would at least suggest pgrep instead of ps | grep, since pgrep will search directly for a process by name and won't find anything that just happens to include the same string.
daemon_pid=`pgrep -x -c fsdaemon`
if [ $daemon_pid -eq 0 ]; then
echo "restarting fsdaemon"
/etc/init.d/fsdaemon restart
fi
The -x means "match exactly", and -c works as with grep.
By the way, it seems a bit misleading to name your variable daemon_pid when it is actually a count.

Resources