grep from screen output and detach - bash

I'm currently writing a bash script which periodically checks for some special words in the server output of a detached screen session, but it enters the session (if grep found something) instead of showing the grepped output. Here is what I've tried:
screen -r foo | grep bar
This gives me the correct return code, but doesn't detach the session afterwards! I also tried && screen -d but that changes nothing.
So how can my script tell me if "bar" is in the output of the server running in my "foo" screen session?

Your problem, I think, is that screen doesn't output in a way that can be searched by grep. If it did, then your attempt at screen -r foo | grep bar && screen -d would likely have been the right way to go about it.
I'd suggest starting the initial screen session with the -L option to enable logging. Then you can search the log file for the value you want.

Related

Is there any way to fetch the title of a chromium-browser window via script or command?

I'm working on a project using Libre LePotato with Raspbian for a basic display kiosk. It launches chromium-browser to a specific url, then uses xdotool to type the username and password and hit enter. Once logged in the page refreshes every 5 minutes. Eventually the page forgets the login credentials and needs to be logged into again. The URL does not change between the login screen and the actual display page, but the title of the window does. Is there any way for me to fetch the title of the window? That way I can just create an if/then script that runs xdotool when the window title is Login.
I've tried setting the device up to reboot more frequently in order to hopefully reset the memory cache and log in again on boot up, but the issue occurs too frequently and constant rebooting on a display does not look good.
The proper way to automate this would be through the use of Selenium, Playwright or Puppeteer (I prefer Puppeteer). If you insist though, you can use wmctrl.
For example, I'm using Brave, and let's say the normal output is this (I use Brave Browser):
$ wmctrl -l | grep -i brave
...
0x05400003 0 nullptr Home | Codewars - Brave
...
It lists the window id, a bunch of other stuff along with the title.
Now, the following is the output, when I'm on the sign-in page:
$ wmctrl -l | grep -i brave
...
0x05400b8b 0 nullptr Sign in | Codewars - Brave
...
With that knowledge, creating a script is relatively simple:
#!/usr/bin/env
if wmctrl -l | grep -q 'Sign in | Codewars - Brave'; then
printf '%s\n' 'about to sign in'
else
printf '%s\n' 'not signing in'
fi
Since this is all in a Kiosk, I figure that you won't have any other windows that potentialy interfere with the logic (ex. two codewars windows open at once)

How to listen for, and act upon, a Mac notification using Automator?

Is it possible to listen for a specific notification on Mac and act upon it using Automator?
I regularly use an app that runs a background job then sends a notification when it's finished. The app stays open after the job is finished so I'd like to use Automator to quit the app when the notification is received.
If it's not possible in Automator is there another way I could do this?
More context: the app is actually launched by a Folder Action created using Automator. It detects when a specific SD card is inserted and runs a backup app on that SD card. So maybe there's something I can add to that Folder Action workflow that can detect the notification?
While it's certainly possible to query the sqlite database containing notifications in macOS, it seems to me like an unnecessarily complicated route, and I would first try the following...
In your workflow, add a 'Run Shell Script' action at the end, containing something like this:
while [ $(ps -e | grep "[N]ameOfBackgroundProcess" | wc -l) -gt 0 ]; do
sleep 3
done
killall "NameOfAppToQuit" 1&>2 /dev/null
The while loop checks whether the background job is still running.
ps -e lists all running processes.
grep "[N]ameOf..." gets all lines containing the name. Brackets around the first letter excludes the grep process itself from the output.
wc -l counts the lines.
-gt 0 checks if the number is greater than zero.
When the loop is done, that means the process has exited so we quit the app with killall.
As for the notification route...
I haven't figured everything out, but this might give you a head start:
#!/usr/bin/env bash
# Get the directory of the Notification Center database (works for me in Big Sur):
db_dir=$(lsof -p $(ps aux | grep -m1 usernoted | awk '{ print $2 }')| awk '{ print $NF }' | grep 'db2/db$' | xargs dirname)
# Get the app_id:
app_id=$(sqlite3 "$db_dir"/db 'SELECT app_id FROM app WHERE identifier="com.example.identifier";')
# Get relevant records:
sqlite3 "$db_dir"/db "SELECT * FROM record WHERE app_id='$app_id';"
# And this is where I leave you.
To explore the database in a GUI, try https://sqlitebrowser.org/

pager (less) -- get current scroll position?

I am scripting the display of the output of a script (well, it is just the program git diff) with tmux: Once a filesystem change is detected the shell script executes tmux send-keys q enter C-l "git diff" enter which has it effectively refresh the git diff view.
You might consider this similar to functionality provided by iTerm's coprocesses.
Problem is, I want it on refresh to scroll back to the same position that it was in.
One of the reasons for using tmux is that the window is actually a totally normal and interactive terminal session that can be interacted with as normal to scroll around to look at the full output.
But I want to obtain the scroll position somehow.
Suppose I want to actually do computation on the text content of the terminal window itself, exactly like iTerm2's coprocess does, but so that I can use it on Linux (over ssh). Does tmux provide this ability?
I'm unsure about capturing this with a script, but less -N will show line numbers.
And -jn or --jump-target=n can jump to a location.
About iTerm's coprocesses,
tmux has a command pipe-pane that can be used to pipe the input and output of a shell command to the output and input of a target pane specified by -t.
So if I have a shell program, ~/script.sh for example:
#!/usr/bin/env bash
while read line; do
if [[ "$line" = "are you there?"* ]]; then
echo "echo yes"
fi
done
Note that read line will read every line printed to the pane, i.e. the prompt as well.
I can connect its stdin and stdout to pane 0 in my-session:my-window like so:
tmux pipe-pane -IO -t my-session:my-window.0 "~/script.sh"
and then at the prompt, type echo are you there?, and it responds:
$ echo are you there?
are you there?
$ echo yes
yes
Be careful using -IO together as it can easily cause a feedback loop (I had to kill the tmux server a few times while experimenting with this feature, lol).

How can I make bash terminal to beep when its output screen changes?

I am using gnome-terminal.
Is it possible to make it(or any other terminal) beep whenever its output screen changes (like some new output line came)?
I want it for only one particular window.
Possibly of use:
The GNU screen program has features for monitoring background windows for activity as well as inactivity.
http://www.gnu.org/software/screen/manual/screen.html#Monitor
Something called lTerm has "tabs with activity alerts"
http://lterm.sourceforge.net/
But at this point I'm turning into a meta search engine.
$ ./myprogram | sed 's/$/\a/'
for example
$ for i in {1..10}; do echo $i; sleep 1; done | sed 's/$/\a/'

Problems in sending input to detached 'screen' via readreg and paste

I am trying to send input to a interactive command running via screen. Here is my initial command
screen -L -c ./customrc -S psql -d -m /opt/PostgreSQL/9.0/bin/psql
The above command will run interactive psql in screen detach mode. The customrc is used to define a log file for the output (which I will read from another process by polling)
I am using following two commands to send input to psql running in screen
screen -S psql -X readreg p psqlcommands.sql
screen -S psql -X paste p
The problem is that the above commands do not work unless I reattach screen at least once. Once I have attached screen and detached, the above commands work as expected. I have to launch these commands via background java process hence the interactive shell (bash) is not available. My goal is to run psql in interactive mode and pass input to it and capture its output via a log file.
So far I have tried to run screen via xterm (or konsole or gnome-terminal) in attach mode, use readreg/paste and then detach, but I realise that xterm will not be available in my production environment. I've also tried sending output to /proc//fd/0 but I am unable to emulate 'ENTER' from keyboard (I have to attach and press in order for the output to be accepted by psql). I think pipes and fifo may help but I am unable to figure out how to proceed with them using screen and psql.
I appreciate any further hints or workarounds.
Thank you,
Usman.
Well, you can use
screen -S psql -p 0 -X stuff $'\n'
or better (works for me)
screen -S mname -p 0 -X stuff `echo -ne '\015'`
-p 0 is needed to select the window.
Have you tried this to "press enter" after your readreg and paste?
screen -S psql -X stuff $'\n'
FINAL ANSWER: It is a bug/feature in 'GNU screen' that it needs a DISPLAY atleast once for 'paste' command to work. Following are possible workarounds this problem:
Finally figured out how to utilise psql with pipes and screen. Here is the solution:
mkfifo psql.pipe
screen -L -c ./customrc -S psql -d -m bash -i -c "while (true); do cat psql.pipe; done | /opt/PostgreSQL/9.0/bin/psql -a"
After that, I can cat my commands to the pipe:
cat ./mycommands.sql > psql.pipe
To quit from screen and terminating psql, I used
screen -S psql -X quit
EDIT: (finally) figured out the solution for my problem without using screen command. Meet 'empty' utility.
empty -f -i psql.in -o psql.o -p psql.pid <psqlpath>
This allows psql to run in full interactive mode as opposed to the original solution that I used (in which psql does not run in interactive mode).
Thanks.
Usman
I had this same problem. My workaround was to launch screen attached but pass it a screenrc file where the last command is "detach"
So this is my screenrc
#change the hardstatus settings to give an window list at the bottom of the
#Set this first otherwise messes with bash profile
hardstatus alwayslastline
#screen, with the time and date and with the current window highlighted
#hardstatus string '%{= kG}%-Lw%{= kW}%50> %n%f* %t%{= kG}%+Lw%< %{= kG}%-=%c:%s%{-}'
hardstatus string '%{= kG}[ %{G}%H %{g}][%= %{= kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B} %m-%d %{W}%c %{g}]'
#set scrollback
defscrollback 4096
#detach
detach
Hope this helps
P

Resources