Repository navigation
Expand file tree
/
Copy pathmac_exec.sh
More file actions
executable file
·172 lines (157 loc) · 4.51 KB
/
Copy pathmac_exec.sh
File metadata and controls
executable file
·172 lines (157 loc) · 4.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#!/usr/bin/env bash
# mac_exec.sh — Remote Mac control via SSH
# Usage:
# mac_exec.sh --run "command" [timeout_seconds]
# mac_exec.sh --screenshot [output_path]
# mac_exec.sh --app "open|activate|quit|kill:AppName"
# mac_exec.sh --file "get|put:src:dst"
#
# Config (env vars or ~/.remote-mac.conf):
# MAC_SSH_HOST — SSH host (default: mac.local)
# MAC_SSH_USER — SSH user (default: current user)
# MAC_SSH_PORT — SSH port (default: 22)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/common.sh"
load_config
# --- Channel Detection ---
check_ssh() {
if ssh $SSH_OPTS "$MAC_SSH" "echo ok" &>/dev/null; then
return 0
fi
return 1
}
exec_cmd() {
local cmd="$1"
if ! check_ssh; then
echo '{"error":"Mac SSH unreachable"}' >&2
exit 1
fi
ssh $SSH_OPTS "$MAC_SSH" "$cmd"
}
# --- Actions ---
do_run() {
local cmd="$1"
local tout="${2:-30}"
[[ "$tout" =~ ^[0-9]+$ ]] || { echo "Invalid timeout" >&2; exit 1; }
echo "[ssh→mac] (timeout ${tout}s) $cmd" >&2
local cmd_payload
cmd_payload=$(shell_escape "$cmd")
local remote_cmd
remote_cmd=$(cat <<EOF
if command -v gtimeout >/dev/null; then
gtimeout ${tout} bash -lc ${cmd_payload}
elif command -v timeout >/dev/null; then
timeout ${tout} bash -lc ${cmd_payload}
else
bash -lc ${cmd_payload}
fi
EOF
)
exec_cmd "$remote_cmd"
}
do_screenshot() {
local local_path="${1:-/tmp/mac_screenshot.png}"
local remote_path="/tmp/mac_ss_$$_$RANDOM.png"
echo "[screenshot] → $local_path" >&2
if ! check_ssh; then
echo '{"error":"SSH unreachable"}' >&2
exit 1
fi
ssh $SSH_OPTS "$MAC_SSH" "/usr/sbin/screencapture -x $remote_path"
scp $SCP_OPTS "$MAC_SSH:$remote_path" "$local_path"
ssh $SSH_OPTS "$MAC_SSH" "rm -f $remote_path" 2>/dev/null || true
echo "$local_path"
}
do_app() {
local action="${1%%:*}"
local app="${1#*:}"
echo "[app] $action: $app" >&2
local app_q
app_q=$(shell_escape "$app")
case "$action" in
open)
exec_cmd "open -a ${app_q}"
;;
activate)
exec_cmd "osascript -e 'on run argv' -e 'tell application item 1 of argv to activate' -e 'end run' -- ${app_q}"
;;
quit)
exec_cmd "osascript -e 'on run argv' -e 'tell application item 1 of argv to quit' -e 'end run' -- ${app_q}"
;;
kill)
exec_cmd "pkill -x ${app_q} || true"
;;
*)
echo "Unknown app action: $action (use open|activate|quit|kill)" >&2
exit 1
;;
esac
}
do_file() {
local direction="${1%%:*}"
local rest="${1#*:}"
local src="${rest%%:*}"
local dst="${rest#*:}"
echo "[file] $direction: $src → $dst" >&2
if ! check_ssh; then
echo '{"error":"SSH unreachable"}' >&2
exit 1
fi
# NOTE: remote paths are passed to scp unquoted. Literal quotes break both
# the legacy and SFTP scp protocols (and stop "~" from expanding).
case "$direction" in
get) # Mac → local
scp $SCP_OPTS "$MAC_SSH:$src" "$dst"
echo "Downloaded: $dst"
;;
put) # local → Mac
scp $SCP_OPTS "$src" "$MAC_SSH:$dst"
echo "Uploaded: $dst"
;;
*)
echo "Unknown direction: $direction (use get|put)" >&2
exit 1
;;
esac
}
# --- Main ---
if [ $# -lt 1 ]; then
echo "Usage: $0 --run|--screenshot|--app|--file [args]" >&2
exit 1
fi
case "$1" in
--help|-h)
cat <<'EOF'
Usage:
mac_exec.sh --run "command" [timeout_seconds]
mac_exec.sh --screenshot [output_path]
mac_exec.sh --app "open|activate|quit|kill:AppName"
mac_exec.sh --file "get|put:src:dst"
Config (env vars or ~/.remote-mac.conf):
MAC_SSH_HOST — SSH host (default: mac.local)
MAC_SSH_USER — SSH user (default: current user)
MAC_SSH_PORT — SSH port (default: 22)
EOF
exit 0
;;
--run)
[ -z "${2:-}" ] && { echo "Missing command" >&2; exit 1; }
do_run "$2" "${3:-30}"
;;
--screenshot)
do_screenshot "${2:-/tmp/mac_screenshot.png}"
;;
--app)
[ -z "${2:-}" ] && { echo "Missing: open|activate|quit|kill:AppName" >&2; exit 1; }
do_app "$2"
;;
--file)
[ -z "${2:-}" ] && { echo "Missing: get|put:src:dst" >&2; exit 1; }
do_file "$2"
;;
*)
echo "Unknown option: $1" >&2
exit 1
;;
esac