Run command if screen exists - bash

I have a shell script that is supposed to kill a detached screen session if it exists. The script is
if ! screen -list | grep -q "ScreenName"; then
screen -S ScreenName -X quit
fi
Unfortunately it seems that the screen -S ... -X quit command always runs bc when I run the script and the screen session doesn't exist it still outputs "No screen sessions found." When I remove the ! and the screen session is running, it doesn't kill the running session.
What could the problem be? Thanks

To get rid of the "No screen sessions found" message, redirect the stderr of screen:
screen -list 2>/dev/null
Next, keep in mind that -X doesn't work if the session is password protected.
Then, use -r to let screen know you only want to kill detached sessions, and there's no more need for grep and if.
Putting it all together:
screen -r -S "ScreenName" -X quit 2>/dev/null

grep has a confusing convention for return codes. It returns 0 when a string is found and returns 1 when there is no match. You should omit the ! in the condition.

#Sir Athos answer is pretty good, if you don't want to ignore valid errors, or just want additional ways to do things in the future, you can use this as a reference:
screen -ls 2>&1 | grep '(Detached)' | grep -o 'ScreenName' | xargs -I{} -n 1 -r screen -r -S {} -X quit
screen -ls 2>&1 List sessions, all output to stdout
grep '(Detached)' Filter for detached sessions
grep -o 'ScreenName' Filter for ScreenName and only output ScreenName
xargs -I{} -n 1 -r screen -r -S {} -X quit Run output through xargs -n 1 one at a time, -r don't run if there is no output, -I{} use {} as the replacement location for your argument since it's not at the end, and run your command
Code Sample:
evan> screen -ls
There are screens on:
15491.pts-2.x (08/29/2013 10:43:53 AM) (Detached)
31676.pts-41.x (08/28/2013 10:55:00 AM) (Attached)
2 Sockets in /var/run/screen/S-evan.
evan> screen -ls 2>&1 | grep '(Detached)' | grep -o '15491.pts-2.x' | xargs -I{} -n 1 -r screen -r -S {} -X quit
evan> screen -ls
There is a screen on:
31676.pts-41.x (08/28/2013 10:55:00 AM) (Attached)
1 Socket in /var/run/screen/S-evan.
evan> screen -ls 2>&1 | grep '(Detached)' | grep -o '15491.pts-2.x' | xargs -I{} -n 1 -r screen -r -S {} -X quit
evan>

Related

How to run a command like xargs on a grep output of a pipe of a previous xargs from a command in Bash

I'm trying to understand what's happening here out of curiosity, even though I can just copy and paste the output of the terminal to do what I need to do. The following command does not print anything.
ls /opt/local/var/macports/registry/portfiles -1 | sed 's/-.*//g' | sort -u | parallel "sudo port -N install" {} 2>&1 | grep -Po "Use '\K.*(?=')" | parallel "{}"
The directory I call ls on contains a bunch of filenames starting with the string I want to extract that ends at the first dash (so stringexample-4.2009 pipes stringexample into parallel (like xargs but to run each line separately). After running the command sudo port install <stringexample>, I get error outputs like so:
Unable to activate port <stringexample>. Use 'port -f activate <stringexample>' to force the activation.
Now, I wish to run port -f activate <stringexample>. However, I cannot seem to do anything with the output port -f activate gettext that I get to the terminal.
I cannot even do ... | grep -Po "Use '\K.*(?=')" | xargs echo or ... | grep -Po "Use '\K.*(?=')" >> commands_to_run.txt (the output stream to file only creates an empty file), despite the shorter part of the command:
ls /opt/local/var/macports/registry/portfiles -1 | sed 's/-.*//g' | sort -u | parallel "sudo port -N install {}" 2>&1 | grep -Po "Use '\K.*(?=')"
printing the commands to the terminal. Why does the pipe operator not work here? If the commands I wish to run are outputting to the terminal, surely there's got to be a way to capture them.

How do I not show the processes that I can't kill with 'kill + [pid number]' command?

I was working on a project "make a task manager in linux" at school
I used ps -u [username] -o stat,cmd --sort=-pid | awk '{print $2$3$4}' command to get cmd names from the ps command
If I use this command, I see the part of the result like this :
awk{print$2$3$4}
ps-u[username]
when I try to terminate those process using the pid of each process, it won't terminate them because their PID doesn't exist.
How could I not show those awk{print$2$3$4} and ps-u[username] ???
I couldn't think of any idea
ps -u [username] -o stat,cmd --sort=-pid | awk '{print $2$3$4}'
You can't kill them because they were only alive while the commands were running, which was the same command you used to generate that output.
There's a few ways you can suppress these. I think the easiest would be to filter them out in your awk script.:
ps -u [username] -o stat,cmd --sort=-pid | awk '$2!="awk" && $2!="ps"{print $2$3$4}'
JNevill's solution excludes every running awk or ps process. I think it's better to exclude processes on tty. Also, you aren't getting complete commands with how you use awk. I (kind of) solved it using sed.
$ ps -u $USER -o stat,tty,cmd --sort=-pid | grep -v `ps -h -o tty $$` | sed -r 's/.* (.*)$/\1/'
You can test it with the following command. I opened man ps in another terminal.
$ ps -u $USER -o stat,tty,cmd --sort=-pid | grep -v `ps -h -o tty $$` | grep -E '(ps|grep)'
S+ pts/14 man ps
The downside is, besides excluding ps and grep, it excludes your application as well.

CPU optimization for gif wallpaper

I'm using xubuntu with xfc4, for pure fun I tried to make a script which allows me to put a gif as a desktop wallpaper because this is not a default feature in xfce4.
I've already made a script which seem to work pretty fine excepted that the CPU get in a great trouble with it. So is there a way to optimize this code to do the same thing but stay friend with my CPU?
BG_GIF=/home/grasteau/Pictures/walpapper.gif
DURATION=$(exiftool -Duration walpapper.gif | sed 's/ //g' | sed 's/Duration://g' | sed 's/s//g')
PATH_IMAGE=/
mkdir -p /dev/shm/background
rm -f /dev/shm/background/*
gm convert $BG_GIF +adjoin /dev/shm/background/target%d.png
NUMBER_OF_FRAME=$(bc <<< "$(ls -1 /dev/shm/background | wc -l) - 1")
DELAY=$(bc <<< "scale=3; $DURATION/$NUMBER_OF_FRAME")
while true
do
for i in $(seq 0 $NUMBER_OF_FRAME);
do
PATH_IMAGE="/dev/shm/background/target$i.png"
xfconf-query -c xfce4-desktop -l | grep "last-image$" | while read -r line
do
xfconf-query -c xfce4-desktop -p $line -s $PATH_IMAGE
done
sleep $DELAY
done
done

Pipe grep response to a second command?

Here's the command I'm currently running:
curl 'http://test.com/?id=12345' | grep -o -P '(?<=content="2;url=).*?(?=")'
The response from this command is a URL, like this:
$ curl 'http://test.com/?id=12345' | grep -o -P '(?<=content="2;url=).*?(?=")'
http://google.com
I want to use whatever that URL is to essentially do this:
curl 'http://test.com/?id=12345' | grep -o -P '(?<=content="2;url=).*?(?=")' | curl 'http://google.com'
Is there any simple way to do this all in one line?
Use xargs with a place holder for the output from stdin with the -I{} flag as below. The -r flag is to ensure the curl command is not invoked on a empty output from previous grep output.
curl 'http://test.com/?id=12345' | grep -o -P '(?<=content="2;url=).*?(?=")' | xargs -r -I{} curl {}
A small description about the flags, -I and -r from the GNU xargs man page,
-I replace-str
Replace occurrences of replace-str in the initial-arguments with
names read from standard input.
-r, --no-run-if-empty
If the standard input does not contain any nonblanks, do not run
the command. Normally, the command is run once even if there is
no input. This option is a GNU extension
(or) if you are looking for a bash approach without other tools,
curl 'http://test.com/?id=12345' | grep -o -P '(?<=content="2;url=).*?(?=")' | while read line; do [ ! -z "$line" ] && curl "$line"; done

Bash piping issue

I need to execute the following grep query as an argument for konsole (the kde terminal)
grep -R -i -n -A 2 -B 2 --color=always -R "searchtext" * | less -R
works for the current terminal.
konsole --workdir `pwd` -e grep -R -i -n -A 2 -B 2 --color=always -R "searchtext" * | less -R
works, but the konsole window displays the grep query without less pipe.
Ideally I want konsole to spawn as seperate process with konsole &
and send the grep command with less as an argument for konsole -e
You need to run the pipe in a shell.
konsole --workdir pwd -e bash -c 'grep -R -i -n -A 2 -B 2 --color=always -R "searchtext" * | less -R'

Resources