When I run defaults read 'com.apple.Safari' in terminal, I get a whole lot of information, especially the value I'm interested in: defaults read 'com.apple.Safari' 'NSWindow Frame BrowserWindowFrame'.
But when running in AppleScript, the result is completely different:
do shell script "defaults read 'com.apple.Safari'"
(*
{
ResetCloudHistory = 1;
cloudBookmarksMigrationEligibilityDataInvalidated = 1;
}
*)
So when I run the AppleScript asking for the key I'm interested in, I get the error message:
The domain/default pair of (com.apple.Safari, NSWindow Frame BrowserWindowFrame) does not exist
I assume this is due to security.
Does anyone know a way I can make my applescript access this setting and later write to it?
P.S. Using Mac OS 10.14 Mojave
In order to read the sandboxed version of com.apple.Safari.plist in macOS Mojave from Script Editor, you need to add Script Editor to: System Preferences > Security & Privacy > Privacy > Full Disk Access.
Then:
do shell script "defaults read 'com.apple.Safari' 'NSWindow Frame BrowserWindowFrame'"
Returns, e.g.,:
"88 73 1264 804 0 0 1440 877 "
Note that if the do shell script command is run by some other method, then the application involved in that method would need to be added to: System Preferences > Security & Privacy > Privacy > Full Disk Access
In macOS Mojave, to see the difference, from Terminal:
$ defaults read ~/Library/Preferences/com.apple.Safari.plist
{
IncludeDevelopMenu = 1;
WebKitDeveloperExtrasEnabledPreferenceKey = 1;
"WebKitPreferences.developerExtrasEnabled" = 1;
}
$
$ defaults read ~/Library/Containers/com.apple.Safari/Data/Library/Preferences/com.apple.Safari.plist 'NSWindow Frame BrowserWindowFrame'
88 73 1264 804 0 0 1440 877
$
However, the same later command using the do shell script command:
do shell script "defaults read 'com.apple.Safari' 'NSWindow Frame BrowserWindowFrame'"
It is obviously accessing the sandboxed version of com.apple.Safari.plist, based on what's returned.
Related
I just have started to use crontab and have some problems with it. I have already read some posts about how to use it on macOS, but it still not working.
So,
I write crontab -e, then edit it to
*/1 * * * * cliclick -w 1 m:3,3 (for example) - which mean repeat click in x=3;y=3 every 1 min.
And nothing has changed.
But, when I use just this command from the terminal everything is ok.
I have already tried to create a script.sh file, and the same situation: from hand-command it works, and from crontab isn't.
Maybe, I do something wrong?
UPDATE: Full disk access crontab has.
UPDATE2:
I tried do it again on the BigSur. First of all I use a more simple command like echo:
* * * * * echo 'test' >> /*/Desktop/text.txt
And it works well. After that, I write my own script.sh
echo '2test' >> /Users/***/Desktop/t.txt
/usr/local/bin/cliclick -w 1 m:1,3
cliclick -w 1 m:55,44
And it the cliclick not working, as the other bin files located in /usr/local/bin/ (cliclick located in this path)
Note, that if I execute ./script.sh then cliclick works fine in both cases.
I thoroughly googled and found that run cliclick (and other) is NOT possible though crontab: https://github.com/BlueM/cliclick/issues/103
My Problem was, that cron had no access to the Disk, so it couldn't run my script. I had to give Full Disk Access for /usr/sbin/cron
See this blog post: https://blog.bejarano.io/fixing-cron-jobs-in-mojave/
(macOS Big Sur Version 11.2.3)
First you have to verify whether a cron exists or not with crontab -l.
After you're done creating a cronjob, you'll see something like "crontab: installing new crontab". (If you don't see this message, the job hasn't been created and will not show when you run crontab -l)
To ensure that the cronjob executes, I've had to do what #roNn23 and #berkinet have suggested. Elaborating in case the linked article goes down:
Give "Full Disk Access" (under System Preferences > Security & Privacy > Privacy) to:-
/usr/sbin/cron using the Go to folder shortcut "command + shift + G"
Terminal.app
Give terminal.app Full Disk Access.
You need to authorize Full Disk Access for terminal.app in Settings > Security & Privacy > Privacy.
You can check if there are any errors while running the cron by configuring it as below.
*/1 * * * * cliclick -w 1 m:3,3 >> output.log 2>&1
the last part 2>&1 will redirect the STDERR to the output.log as well.
How to find out if script launched using terminal console or without, in gui by .desktop file for example?
I have look over env output and some variables looks promising to check, like test $TERM var. But I want known for sure and a compatible/portable way to do it.
This is needed for script what will have two behaviors for user input, fallback to terminal read or gui input.
The answer by #LeonidMew is incomplete and somewhat incorrect.
You should not detect GUI by presence of STDIN (that's what [ -t 0 ] test does). There are cases when none of STDIN and GUI are available, e.g. when you run the script over ssh session in non-interactive mode. This happens often for CI deploys.
Correct answer heavily depends on your task, in general there are 4 distinct environments:
App is run non-interactively, e.g. from ssh command, spawned as child process without STDIO attached, etc. GUI is missing, STDIN is missing.
App is run interactively from X-session with .desktop file or alike. GUI is present, STDIN is missing.
App is run interactively from linux terminal (ssh, bare text console, hosting recovery console, etc.). GUI is missing, STDIN is present. App can interact with user in text mode via STDIN.
App is run interactively from GUI terminal app, like xterm. GUI is present, STDIN is present.
There are 2 basic tests that can help to identify the environment:
GUI test - whether app can interact with user using graphical windows: test for $DISPLAY env variable.
STDIN test - whether app can interact with user using text console: test for file descriptor 0 (aka STDIN) with if [ -t 0 ]; ...
Combining these two test will give you the environment:
test 1 false + test 2 false: case 1 -- no user interaction available
test 1 true + test 2 false: case 2 -- interact via XWindows
test 1 false + test 2 true: case 3 -- interact via STDIN/console
test 1 true + test 2 true: case 4 -- XWindows or STDIN/console, whichever is preferred
if [ -t 0 ]; then echo "in a terminal"; fi
That tests file descriptor 0, which is stdin. If you're launching your script as a GUI, that test should be false.
Author: glenn jackman
This won't work if the script is run from a terminal, but with input
redirected. – Gordon Davisson
so for the purpose of this discussion, terminal emulator is being
conflated with linux console, and both are being distinguished from a
"gui method" which I'd thought xterm to be, as it opens in a gui... -
JosephHarriott
Purpose of this question was writing script interface usable for text or gui if script run by .desktop shortcut or other gui method.
Or:
$ [ -t 0 ] && echo "in a terminal" || echo "something else"
in a terminal
I want to take a screen capture of a dynamic webpage. Content changes every hour of the day.
My script works fine but:
1. I want to make sure the script is active while the iMac (OS X
Yosemite Version 10.10.5) is in sleep modus or when the screen saver is active.
2. Second problem is that the screen capture must be my desired webpage
and not the active window.
set dFolder to "~/Desktop/screencapture/"
do shell script ("mkdir -p " & dFolder)
set i to 0
repeat 24 times
do shell script "open -a Safari http://www.lipsum.com/"
do shell script ("screencapture " & dFolder & "frame-" & i & ".png")
delay 3600 -- Wait for 3600 seconds.
set i to i + 1
end repeat
I don't believe you can do what you want with the tool you have chosen. I think you need to use webkit2png.
Go to GitHub and download the webkit2png script from here. It is just a Python script in a single file. You will need to edit it around line 420 so it looks like this (there are 3 lines added in the middle):
# Hide the dock icon (needs to run before NSApplication.sharedApplication)
AppKit.NSBundle.mainBundle().infoDictionary()['LSBackgroundOnly'] = '1'
# Handles ATS HTTPS requirement introduced in El Cap
if options.ignore_ssl_check:
AppKit.NSBundle.mainBundle().infoDictionary()['NSAppTransportSecurity'] = dict(NSAllowsArbitraryLoads = True)
app = AppKit.NSApplication.sharedApplication()
Now you can download your website whether the screensaver is running or not and regardless of which window has focus using:
./webkit2png --ignore-ssl-check -W 800 -H 600 -F -o MYSITE http://www.lipsum.com/
You can use this with your existing Applescript - just put your "frame-" & i after the MYSITE part.
You will probably need to put the full path instead of ./webkit2png, so, depending where you save the script, you may need to use something like /Users/Geonemec/webkit2png --ignore-ssl-check ...
You can get help on the options it accepts by running:
webkit2png -h
set dFolder to "~/Desktop/screencapture/"
do shell script ("mkdir -p " & dFolder)
set i to 1
repeat 2 times
set DeTijd to time string of (current date)
tell application "Terminal"
activate
do script ("webkit2png --ignore-ssl-check -F -o PR" & DeTijd & " " & "http://www.google.com")
end tell
delay 3600 -- Wait for 3600 seconds = 1 hour.
set i to i + 1
end repeat
This works fine.
Tx for the help.
Google suggests
echo "input" | osascript filename.scpt
with filename.scpt
set stdin to do shell script "cat"
display dialog stdin
However, I could get only blank dialog: it has no text. How can I get stdin from AppleScript at the version?
My OS version is OSX 10.8 Mountain Lion.
Sorry, not enough reputation to comment on answers, but I think there's something important worth pointing out here...
The solution in #regulus6633's answer is not the same as piping data into osascript. It's simply stuffing the entire pipe contents (in this case, echo output) into a variable and passing that to osascript as a commandline argument.
This solution may not work as expected depending on what's in your pipe (maybe your shell also plays a part?)... for example, if there are null (\0) characters in there:
$ var=$(echo -en 'ABC\0DEF')
Now you might think var contains the strings "ABC" and "DEF" delimited by a null character, but it doesn't. The null character is gone:
$ echo -n "$var" | wc -c
6
However, using #phs's answer (a true pipe), you get your zero:
$ echo -en 'ABC\0DEF' | osascript 3<&0 <<EOF
> on run argv
> return length of (do shell script "cat 0<&3")
> end run
>EOF
7
But that's just using zeros. Try passing some random binary data into osascript as a commandline argument:
$ var=$(head -c8 /dev/random)
$ osascript - "$var" <<EOF
> on run argv
> return length of (item 1 of argv)
> end run
>EOF
execution error: Can’t make some data into the expected type. (-1700)
Once again, #phs's answer will handle this fine:
$ head -c8 /dev/random | osascript 3<&0 <<EOF
> on run argv
> return length of (do shell script "cat 0<&3")
> end run
>EOF
8
According to this thread, as of 10.8 AppleScript now aggressively closes standard in. By sliding it out of the way to an unused file descriptor, it can be saved. Here's an example of doing that in bash.
Here we get at it again with a cat subprocess reading from the magic fd.
echo world | osascript 3<&0 <<'APPLESCRIPT'
on run argv
set stdin to do shell script "cat 0<&3"
return "hello, " & stdin
end run
APPLESCRIPT
Will give you:
hello, world
I know that "set stdin to do shell script "cat"" used to work. I can't get it to work in 10.8 though and I'm not sure when it stopped working. Anyway, you basically need to get the echo command output into a variable which can then be used as an argument in the osascript command. Your applescript needs to handle arguments too (on run argv). And finally, when you use osascript you must tell an application to "display dialog" otherwise it will error.
So with all that said here's a simple applescript which handles arguments. Make this the code of filename.scpt.
on run argv
repeat with i from 1 to count of argv
tell application "Finder"
activate
display dialog (item i of argv)
end tell
end repeat
end run
Here's the shell command to run...
var=$(echo "sending some text to an applescript"); osascript ~/Desktop/filename.scpt "$var"
I hope that helps. Good luck.
Late to this, but the original AppleScript seems to try to do something not allowed with osascript.
If in the original filename.scpt this line:
display dialog stdin
Is changed to:
tell application "System Events" to display dialog stdin
Then passing a value via stdin (as opposed to command line arguments) definitely still works in 10.7.5 Lion, maybe 10.8 Mountain Lion too.
I'm trying to debug my application on Mac OS X Mountain Lion using a bash script which is used to open the application with several input methods. Though I would like to the script to quit running with a short description what happened, if it encounters any error signals (without set -e).
Script is constructed in a following manner:
#!/bin/bash
#
...
while true
do
for input in $INPUTS
do
/path/to/app $input 2> mylog.log &
sleep 2
tail -2 /private/var/log/system.log | grep $ERROR &&
echo $input &&
exit 1;
test $? -gt 127 &&
echo $input &&
exit 2;
# nothing happened, kill the app and continue with a new test
pkill -9 app
done
done
And I've tried to debug the script by manually sending
pkill -SIGSEGV app
in Terminal.
I'm trying to get the script to print the output to the command line (hence the '&' in the app command) and also to the log file (2>), but it looks like if a crash occurred, it doesn't print the application log properly neither to the file nor terminal and the script just keeps running. Also, somehow the grep from system.log does not catch the crashes.
What would be a better option to monitor and catch application crashes in a shell script on Mac? I've done similar tests on Linux and they worked fine.
EDIT: I am also open for suggestions on other methods for monitoring crashes than a shell script. :-)