3

I'm trying to make a script to either quit compton if it's running or start it if it's not running. I've read from man that it should exit 1 if process is found, so I've tried to make a script that uses that... However this just doesn't work, It starts if it's closed but doesn't close it. what am I doing wrong ??

#!/bin/bash


status=$(pgrep compton 2>&1)

if [[ $status == 1 ]];
    then
        killall compton
    else
        exec compton -b
fi

echo $status
  • 1
    0 or 1 is exit status, but $(...) captures output. – Charles Duffy Mar 19 at 23:41
  • grab $? . do man bash. – user2497 Mar 20 at 19:09
8

You are getting the pgrep output in your status variable. It's just not the output that you expect it to be.

pgrep outputs the process IDs (PIDs) of the processes matching the pattern that you give it. If there is a process whose name matches compton, then $status would be the PID of that process, or of those processes. pgrep also returns an exit status, but an exit status is not captured by a command substitution as a string.

In your test, you compare $status against 1. It is unlikely that compton has PID 1.


If you want to kill any compton process if they exist, and start compton -b if no compton process exists, you may do that with

#!/bin/sh

if ! pkill compton; then
    exec compton -b
fi

This uses the exit status of pkill. The pkill tool works in an equivalent way to pgrep (they are usually distributed and installed as a pair) but instead of outputting PIDs of matching processes like pgrep would do, pkill sends the TERM signal (by default) to the matching processes.

The if keyword uses the exit status of the command that you use with it.

The ! inverts the sense of the test so that

  • If pkill compton succeeds, it means that there was one or several compton processes that have now been killed, or at least signalled, and exec compton -b will not be executed.

  • If pkill compton fails (no process matched the name, or there was some internal error in pkill), the body of the if statement would call your exec compton -b, which would replace the shell process with the process resulting from running compton -b.

5

You should control exit status of pgrep process which will be in $? variable. Or check if $status variable where you're storing the output of pgrep is f.e. non zero-length string. The script in the question checks whether string in variable status is "1"

so

#!/bin/bash
pgrep compton >/dev/null

if [[ $? -eq 0 ]]
then
    killall compton
else
    exec compton -b
fi

or

#!/bin/bash
status=$(pgrep compton 2>&1)

if [[ -n "$status" ]]
then
    killall compton
else
    exec compton -b
fi
  • 3
    if pgrep compton >/dev/null; then is the better practice, so one doesn't directly inspect $? at all. In addition to avoiding bugs where $? refers to a different command than you think it does when editing code to add logging or such, this also means that set -e will no longer treat pgrep returning 1 as cause to exit the script (because branching on its exit status marks it as "checked"). – Charles Duffy Mar 19 at 23:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.