Check if display is sleeping in Applescript - applescript

I'm trying to check if the display is sleeping, then execute some code in AppleScript.
So far I've tried this-
set display_sleep_state to do shell script "ioreg -n IODisplayWrangler |grep -i IOPowerManagement"
if display_sleep_state contains sleeping then
-- Display is asleep
else if display_sleep_state contains awake then
-- Display is awake
else
-- We don't know.
end if
I found that here- https://superuser.com/questions/182018/determine-macs-screen-state-using-applescript
But display_sleep_state does not contain sleeping or awake.
I also tried this, which is pretty much the same except it sets the variables
delay 6 -- test with display awake, then test with display asleep (display sleep hotkeys are ctrl+shift+eject)
set sleeping to 1
set awake to 4
set display_sleep_state to do shell script "ioreg -n IODisplayWrangler |grep -i IOPowerManagement"
if display_sleep_state contains sleeping then
say "display asleep"
else if display_sleep_state contains awake then
say "display awake"
else
say "unknown"
end if
source- http://macscripter.net/viewtopic.php?id=25003
But that also does not work and will switch between saying it's sleeping or awake randomly.
Anyone know how to do this?

First of all, when you use a "do shell script" command the results are given back to you as text. Therefore your if statement must check for some text. As such your if statement should look like this... notice the quotes making the word sleeping into text.
if display_sleep_state contains "sleeping" then
Next, you need to know if "sleeping" is in the text returned from from the "do shell script" command. So run that command by itself and look at the text you get back. Look how the text changes when a display is awake versus sleeping and you'll find words you can use in your if statement to determine the display state. I don't have a sleeping display so I can't help you with that. Good luck.
do shell script "ioreg -n IODisplayWrangler |grep -i IOPowerManagement"

Related

Is there a way to terminate a running process (zscroll) after the end of a while loop in a bash script

I am writing a little script which looks at the output of spotify to determine whether the music stops or starts again, refreshing title and artist after every new start of the playback. Sometimes, the song information is a bit too long, so i am using zscroll to, well, scroll through the line.
#!/usr/bin/env bash
maxlength=50
spotify --show-console 2>&1 |
grep -P --line-buffered "Playing music" |
while read line
do
if [[ $line == *"true"* ]]; then
sleep 0.3
playerctl --player=spotify metadata --format '{{ title }} - {{ artist }}' |
zscroll -l "$maxlength"
# cut -c 1-$maxlength
# cut works wonderful, i am just missing a bit of text, so its not an option
else
echo "music stopped!"
fi
done
This works fine, however, only for the first song. Going to the next, it just continues to scroll through the old song (i suspect there isn't even a new iteration, as the zscroll process isn't finished yet) — is there a way to terminate the running zscroll process with every iteration of the loop?
if it's about the OS - i use arch btw
The problem with your solution is: how should zscroll know when the title stops playing? You read the currently playing title with playerctl in order to transfer it to zscroll. zscroll takes the text and displays it. Forever. Nobody informs zscroll that the music has been stopped.
It is probably easier to run zscroll the way it is intended by its author. See the example "Continually update the playing song" in the manual page of zscroll.
Create a script spotify.sh, which uses playerctl to read the currently played title.
#!/usr/bin/env bash
case $(playerctl --player=spotify status) in
Playing)
playerctl --player=spotify metadata --format '{{ title }} - {{ artist }}'
;;
Paused)
echo "music stopped!"
;;
esac
Then start spotify. (I had to add the --no-zygote option on my system to stop spotify from instantly crashing.)
spotify &
And then run zscroll with the script.
zscroll -n f -u t -U 1 ./spotify.sh
zscroll calls the spotify.sh script in an endless loop once per second and checks for changes. Whenever the output of the script changes, the new text will be displayed. It is not necessary to parse the console output of spotify. The disadvantage of this solution is, that playerctl is executed about 480 times for a 4 minute song.
Your solution will call playerctl only when necessary. But your approach requires that you have to run zscroll in the background to be able to read the next event from the console output. Whenever a new event arrives, you have to kill the old zscroll background job, to start the new one with the new title text.

Pause script by keyboard input

(Sorry for my bad english.) I would like to pause a running script by pressing the [SPACE] bar. The script must run, until the user not press the [SPACE] bar, then pause 20 seconds, and run forth. How can i continuously watch the keyboard input while the script is running?
One way to do it:
#!/bin/bash -eu
script(){ #a mock for your script
while :; do
echo working
sleep 1
done
}
set -m #use job control
script & #run it in the background in a separate process group
read -sd ' ' #silently read until a space is read
kill -STOP -$! #stop the background process group
sleep 2 #wait 2 seconds (change it to 20 for your case)
kill -CONT -$! #resume the background process group
fg #put it in the forground so it's killable with Ctrl+C
I think the most simple way is to implement a script with checkpoints, which tests if a pause is required. Of course, it means your code never call 'long' running command...
A more complex solution is to use SIGPAUSE signal. You can have the main process that execute the script and the side process that catches [SPACE] and emit SIGPAUSE to the main process. Here I see at least two issues:
- how to share the terminal/keyboard between the 2 process (simple if your main script don't expect input from keyboard),
- if the main script starts several processes, you will have to deal with process group...
So it really depends on the complexity of your script. You may consider to rely only on regular Job control provided by Bash.
I suggest to use a controlling script that freezes you busy script:
kill -SIGSTOP ${PID}
and then
kill -SIGCONT ${PID}
to allow the process to continue.
see https://superuser.com/questions/485884/can-a-process-be-frozen-temporarily-in-linux for more detailed explanation.

Improving script efficiency and reliability

I have this sample code which basically repeats ~20k times. The only thing that changes is the id= in the address and in the echo command line. The id= in the address and the id= in the echo line always correspond. I am running this script on a MAC if that is of any importance.
I would like to improve this script if possible to make it more reliable. Sometimes I either lose connectivity or the session to the server is closed and I am required to log in again but the script keeps running oblivious of the situation. I would like the script to pause if for some reason that happens.
Also after the open command is called, sometimes the server takes longer to responds but the osascript command forces the tab to close after the sleep 2 command has elapsed. This puts me in a position where I am not sure if the server actually took into account the url. Increasing the sleep time is not very reliable. What could be done on that front?
[...]
open 'https://domaineName.com/admin/?adsess=dhnchf6ghd5shak4Dghtfffvw&app=core&module=members&controller=members&do=spam&id=1&status=1' -g
sleep 2
osascript -e 'tell window 1 of application "Safari"
close (tabs where index < (get index of current tab))
end'
echo "done id=1"
open 'https://domaineName.com/admin/?adsess=dhnchf6ghd5shak4Dghtfffvw&app=core&module=members&controller=members&do=spam&id=5&status=1' -g
sleep 2
osascript -e 'tell window 1 of application "Safari"
close (tabs where index < (get index of current tab))
end'
echo "done id=5"
[...]
Any help would be appreciated.
Thank you
You will have to write a script that checks if the main script (lets say main.sh) is currently running on the server (like ps -ef|grep main.sh|grep -v grep)
Check the above output and then execute main.sh inside this script.
This way there is no need for using delay/sleep commands.

Applescript - How to run a single bash command from terminal and wait for response before continue?

I have a modelinfo.sh file, if I run it in Terminal it echos/saves results to a TXT file.
To execute this file from Terminal I use command:
./modelinfo.sh -s C8QH74G6DP11
With this command it saves results for given serialnumber: C8QH74G6DP11
I need to get reports for 5000 serials, so I think AppleScript might help me?
I have wrote this code with AppleScript:
tell application "Terminal"
do script ("./modelinfo.sh -s C8TJ14JWDP11") in window 1
do script ("./modelinfo.sh -s C8QH74G6DP12") in window 1
do script ("./modelinfo.sh -s C8QKGFWSDP13") in window 1
do script ("./modelinfo.sh -s C8QKFR5FDP14") in window 1
end tell
With this Code above my IP gets Blocked and I get only report for the first serialnumber.
I have also tried:
on delay duration
set endTime to (current date) + duration
repeat while (current date) is less than endTime
tell AppleScript to delay duration
end repeat
end delay
tell application "Terminal"
do script ("./modelinfo.sh -s C8TJ14JWDP11") in window 1
delay 20
do script ("./modelinfo.sh -s C8QH74G6DP12") in window 1
delay 20
do script ("./modelinfo.sh -s C8QKGFWSDP13") in window 1
delay 20
do script ("./modelinfo.sh -s C8QKFR5FDP14") in window 1
end tell
But this code doesn't help either..
Last I tried:
tell application "Terminal"
do script ("./modelinfo.sh -s C8TJ14JWDP11") in window 1
end tell
This last script I can run as many times as I want and I always gets the report without getting my IP blocked.
It looks like Applescript runs all 4 serials at once even I get IP blocked?
Since I am able to run single check multiple times without getting blocked.
Can anyone please help and point me in right direction?
Is it possible to this with Applescript?
Or can I make a new bash file which runs all my 5000 commands 1 by 1?
Thank you
Updated Answer
If you want to count the lines and give an indication of progress, replace the code below with this:
#!/bin/bash
declare -i total
total=$(wc -l <sn.txt) # count the lines in sn.txt
i=1
while read sn; do
echo "Fetching $sn ($i of $total)"
./modelinfo.sh -s "$sn"
((i++))
done < sn.txt
Original Answer
No idea why anyone would use Applescript for this - it is clearly a simple bash script to run from Terminal.
Assume your serial numbers are saved in a file called sn.txt like this:
C8QH74G6DP11
C8TJ14JWDP11
C8QH74G6DP12
C8QKGFWSDP13
You would then save the following in a file called fetch in your HOME directory. It reads your serial numbers one at a time and fetches them.
#!/bin/bash
while read sn; do
echo Fetching $sn...
./modelinfo.sh -s "$sn"
done < sn.txt
Then you would go into Terminal and type the following to make it executable:
chmod +x fetch
and then you can run it by typing
./fetch
You start Terminal by holding down Command and tapping the Spacebar then typing Ter and Spotlight will guess you mean Terminal, then you just hit Enter to actually start it.
Well, here is the common approach in Applescript to use the approach you are trying.
property serialList: {"C8TJ14JWDP11", "C8QH74G6DP12", "C8QKGFWSDP13", "C8QKFR5FDP14"}
tell application "Terminal"
repeat with aSerial in serialList
do script ("./modelinfo.sh -s " & aSerial) in window 1
delay 20
end
This should work. However, the state of the terminal window needs to be finished with the process and ready for the next call for this to work, so a delay of 20 may be too simplistic. Put the above coded inside a try block, to see any error.
try
-- above code goes here
on error err
display dialog err
end try
Another approach however, is to include the shell commands directly in an Applescript without going through the Terminal app, using
do shell script
You'll have to post the contents of your modelinfo.sh file to get a sense of that possibility.

How to make bash interpreter stop until a command is finished?

I have a bash script with a loop that calls a hard calculation routine every iteration. I use the results from every calculation as input to the next. I need make bash stop the script reading until every calculation is finished.
for i in $(cat calculation-list.txt)
do
./calculation
(other commands)
done
I know the sleep program, and i used to use it, but now the time of the calculations varies greatly.
Thanks for any help you can give.
P.s>
The "./calculation" is another program, and a subprocess is opened. Then the script passes instantly to next step, but I get an error in the calculation because the last is not finished yet.
If your calculation daemon will work with a precreated empty logfile, then the inotify-tools package might serve:
touch $logfile
inotifywait -qqe close $logfile & ipid=$!
./calculation
wait $ipid
(edit: stripped a stray semicolon)
if it closes the file just once.
If it's doing an open/write/close loop, perhaps you can mod the daemon process to wrap some other filesystem event around the execution? `
#!/bin/sh
# Uglier, but handles logfile being closed multiple times before exit:
# Have the ./calculation start this shell script, perhaps by substituting
# this for the program it's starting
trap 'echo >closed-on-calculation-exit' 0 1 2 3 15
./real-calculation-daemon-program
Well, guys, I've solved my problem with a different approach. When the calculation is finished a logfile is created. I wrote then a simple until loop with a sleep command. Although this is very ugly, it works for me and it's enough.
for i in $(cat calculation-list.txt)
do
(calculations routine)
until [[ -f $logfile ]]; do
sleep 60
done
(other commands)
done
Easy. Get the process ID (PID) via some awk magic and then use wait too wait for that PID to end. Here are the details on wait from the advanced Bash scripting guide:
Suspend script execution until all jobs running in background have
terminated, or until the job number or process ID specified as an
option terminates. Returns the exit status of waited-for command.
You may use the wait command to prevent a script from exiting before a
background job finishes executing (this would create a dreaded orphan
process).
And using it within your code should work like this:
for i in $(cat calculation-list.txt)
do
./calculation >/dev/null 2>&1 & CALCULATION_PID=(`jobs -l | awk '{print $2}'`);
wait ${CALCULATION_PID}
(other commands)
done

Resources