I have multiple Bash scripts that work fine from Terminal.app, but fail if run from do shell script
. Can’t decide if I’m lazy (as I likely could have rewritten all of them by now) or what, but I’d prefer not to have AppleScript-specific versions of them.
I crater in this routine (though this same technique is used elsewhere) at the exec
call. Can we not open file descriptors directly in do shell script
’s limitations? Would a pseudoterminal fix the problem?
I’m only a little over a decade late to the party and don’t know how
Setup() {
## Create STDLOG (like STDOUT but dedicated to logging)
if [[ ! -t 3 ]]; then
exec 3>&1 # 1 is stdout, 3 is the fd to assign stdout
if [[ ! -t 3 ]]; then
StdlogCreationFailure
## NOTREACHED
fi
## Create log directory if needed
if [[ ! -d "${LOG_DIR}" ]]; then
CreateLogDirectory
fi
Log ${LOG_DEBUG} "STDLOG open"
fi
I know little about shell scripting but it looks like your script intends to make a directory, which is likely meant to be in the root directory (PWD) which likely isn’t permitted.
The tech note that apple provided long ago shows the use of redirecting standard error but none of the numbers above ‘2’. Dunno why ‘3’ wouldn’t be allowed though.
it looks like your script intends to make a directory, which is likely meant to be in the root directory (PWD) which likely isn’t permitted.
Non sequitur. The shell script makes directories just fine. And the typical login setup isn’t done for you, but you can (somewhat) trivially set this up yourself using a couple environment variables (e.g., PATH, HOME, etc) when you issue the do shell script
command.
The [tech note] that apple provided long ago shows the use of redirecting standard error but none of the numbers above ‘2’. Dunno why ‘3’ wouldn’t be allowed though.
Read TN2065 w/o it providing any help; it makes no mention of file descriptors at all, outside specifying how to bundle stdout and stderr which you mentioned.
Standard File Descriptors:
- 0 [stdin]
- 1 [stdout]
- 2 [stderr]
Every UN*X file or socket you open gets a file descriptor (typically starting at 3 and incrementing) – using open(2)/fdopen(3) combo is the longhand equivalent of the fopen(3) call most C programmers use.
The POSIX exec(1) command is how file descriptors are opened/closed using BaSH.
Where else would one look past the tech note itself?
I have multiple Bash scripts that work fine from Terminal.app, but fail if run from do shell script
.
How are you invoking your script?
Bash isn’t the default shell on MacOS. Even if your account is configured to use bash, do shell script and osascript don’t care and will use zsh (the current flavor of the month).
Unless you explicitly run your script in bash, you can’t make any assumptions as to shell-specific implementations.
To just get going quickly, I was double-launching. Something like:
use AppleScript version "2.5"
property name : "Football"
property scriptname : "lift_every_voice_and_sing.bash"
do shell script "bash -c " & scriptname
Then in "lift_every_voice_and_sing.bash"
:
#! /bin/bash
############################################################
###
### @(#)lift_every_voice_and_sing 1.0.0
###
############################################################
## Environment
# Darwin: 17.7.0 (x86_64-apple-darwin17)
# Bash: 3.2.57
## Bash options
set -o errexit
set -o nounset
#set -o xtrace
set -o pipefail
declare -i retcode=0
echo "ENV: $(env)"
export PATH=/usr/local/bin:$PATH
export HOME=/Users/$USER
## Run actual script
(cd $HOME/Projects/nfl/bin; ./blue_80_set_hut.bash)
retcode=$?
if [[ $retcode -eq 0 ]]; then
echo "all good"
else
echo "fubar"
fi
exit $retcode
The Bash script "blue_80_set_hut.bash"
does the actual work (where the POSIX exec
call is failing).
This style double-launch was done attempting to get something working quickly integrating the two languages, fixing any discrepancies here.
As I can’t find enough information to fix my file descriptor problem, I may swap direction and make my AppleScript
run via Bash
instead.
Maybe instead use something like "applescript_runner.scpt"
:
---
--- @(#)applescript_runner 1.0.0
---
use AppleScript version "2.5"
property name : "AppleScript Runner"
property author : "Martin Michel"
property version : "1.0.0"
on run {scriptfile}
tell application "AppleScript Runner"
do script scriptfile
end tell
end run
and have another (unprovided) AppleScript
"update_scores.scpt"
to update the Numbers
spreadsheet.
Somewhere in "update_numbers.bash"
:
#! /bin/bash
############################################################
###
### @(#)update_numbers 1.0.0
###
############################################################
## Environment
# Darwin: 17.7.0 (x86_64-apple-darwin17)
# Bash: 3.2.57
## Bash options
set -o errexit
set -o nounset
#set -o xtrace
set -o pipefail
## Binaries
declare -r OSASCRIPT="osascript"
declare -ar osProvided=(
"${OSASCRIPT}"
)
## AppleScript paths *must* be located somewhere under user's home directory
declare -r _PROJ_HOME="${HOME}/Projects/nfl" # awful to embed this though
## Filesystem
declare -r AS_DIR="${_PROJ_HOME}/AS"
## AppleScript
declare -r applescript_runner="${AS_DIR}/applescript_runner.scpt"
declare -r numbers_applescript="${AS_DIR}/update_scores.scpt"
## Functions
UpdateScores() {
## Runner needed to backdoor allowing user interaction (per u/Martin_Michel)
${OSASCRIPT} ${applescript_runner} ${numbers_applescript}
}
...