I'm trying to make this AppleScript alert me whenever a host comes on or offline. All works fine if I change the do shell script line to set connected to true/false, so I know the rest of the code works. But the do shell script line seems to always return true. When I run it in terminal it works fine, but for some reason in the AppleScript it doesn't. Even if I set the host to a random IP address that returns false every time in terminal, do shell script returns true every time. I got the shell script from this answer.
on run
set oldconnected to false
repeat
set connected to do shell script "ping -o -t 5 My-Host.local >/dev/null && echo yes || echo no" as boolean
if connected and not oldconnected then
display notification "Device has connected"
end if
if not connected and oldconnected then
display notification "Device has disconnected"
end if
set oldconnected to connected
delay 5
end repeat
end run
You're missing some brackets around the do call. Replace:
set connected to do shell script "ping -o -t 5 My-Host.local >/dev/null && echo yes || echo no" as boolean
with:
set connected to (do shell script "ping -o -t 5 My-Host.local >/dev/null && echo yes || echo no") as boolean
and you should be good to go!
Related
I made simple script. file name is sutest.
#!/bin/bash
cd ~/Downloads/redis-4.0.1/src
./redis-server
echo "uid is ${UID}"
echo "user is ${USER}"
echo "username is ${USERNAME}"
I runed script.$ . sutest
But, script code is stopped at ./redis-server.
So I can't see echo messages.
I want to make this kind of script files. How can I do that??
I would be appreciate your help.
Let's say more general case.
myscript1 file executes process like redis-server above.
another myscript2 file executes process like redis-server above.
another myscript3 file executes process like redis-server above.
How can I run three script files simultaneously??
I want to do job in ssh connection.
To make the matter worse, If I can't use screen or tmux??
Add a '&' char at the end of the row
./redis-server &
this char permits to run in backgroud the job, and the script continues.
Just do the echos first:
cd ~/Downloads/redis-4.0.1/src
echo "uid is ${UID}"
echo "user is ${USER}"
echo "username is ${USERNAME}"
exec ./redis-server
The use of exec is a small trick (which you can omit if you prefer): it replaces the shell script with redis-server, so the shell script is no longer running at all. Without exec, you end up with the shell script waiting around for redis-server to finish, which is unnecessary if the script will do nothing further.
If you don't like that for some reason, you can keep the original order:
cd ~/Downloads/redis-4.0.1/src
./redis-server & # run in background
echo "uid is ${UID}"
echo "user is ${USER}"
echo "username is ${USERNAME}"
wait # optional
I have this script:
#!bin/bash
NAME="user"
PIDFILE="openconnect.pid"
CERT="user.crt"
KEY="user.key"
PASS="pass"
HOST="https://example.com"
SCRIPT="/etc/vpnc/vpnc-script"
openconnect -b --script $SCRIPT --pid-file=$PIDFILE -c $CERT -k $KEY --key-password=$PASS --user=$NAME $HOST
It works, but sometimes if something goes wrong (restart of server, or some other issues), it disconnects from VPN. And I need to rerun script again. Is there some way I could modify it or add it in cron job or some other way?
Note. When I run this script I need to enter certificate password. So considering security, I'm wondering where I should keep that password for autoreconnect purposes?
You can detect if openconnect is still running by checking its PID:
pidof openconnect
This return an exit value of 0 if openconnect still runs otherwise non zero.
You would have a script that looks like that [not tested but should give you a hint]:
#!/bin/bash
OPENCONNECT_PID=""
function checkOpenconnect(){
ps -p "${OPENCONNECT_PID}"
# print the status so we can check in the main loop
echo $?
}
function startOpenConnect(){
# start here open connect with your params and grab its pid
openconnect [your params] & OPENCONNECT_PID=$!
}
startOpenConnect
while true
do
# sleep a bit of time
sleep 30
OPENCONNECT_STATUS=$(checkOpenconnect)
[ $OPENCONNECT_STATUS -ne 0 ] && startOpenConnect
done
I'm trying to make an Applescript that connects to a list local ssh machines, with each connection opening in a new terminal window. Prior to attempting the ssh connection, I'd like to ping the client to see if it's available: if it is, run the ssh command, if not then iterates to the next client. When I run the script it seems to work for the first connection but then gives me --> error number -10004 for the remaining clients (and hangs the debugger). Any feedback would be greatly appreciated, thanks!
set hosts to {"10.2.0.199", "10.2.0.11", "10.2.0.91", "10.2.1.591", "10.2.0.41"}
set uname to {"asus_client01", "asrock_comp", "msi003", "gigabyte4", "intel05client"}
tell application "Terminal"
activate
repeat with i from 1 to the count of hosts
set this_uname to item i of uname --extract individual username
set this_host to item i of hosts as string --extract iPv4
set uname_host to this_uname & "#" & this_host
set hostUp to true
try
do shell script "ping -c 1 -t 5 " & this_host
on error
set hostUp to false
display dialog this_host & " seems to be down."
delay 2
end try
if hostUp then
do shell script "ssh " & uname_host
end if
end repeat
end tell
There is a difference between do shell script and do script. The difference is that do shell script is part of the standard script addition and will open an non-interactive shell, execute the given string, and return stdout back to you without any help from another application like Terminal. do shell script should never been used in any other tell application block except itself (me) because you violate some AppleScript securities you can find in AppleScript release and technical notes. do script command is part of AppleScript command in the application Terminal. do script will enter the given string in the targeted window and execute that like you have typed in Terminal yourself. do script is only supported by Terminal application and can't be used outside of it.
So it's either do shell script:
do shell script "ping -o stackoverflow.com
or do script by using the Terminal
tell application "Terminal"
do script "ping -o stackoverflow.com"
end tell
So the total script could look something like this:
set hosts to {"10.2.0.199", "10.2.0.11", "10.2.0.91", "10.2.1.591", "10.2.0.41"}
set uname to {"asus_client01", "asrock_comp", "msi003", "gigabyte4", "intel05client"}
--security check: hosts list can't be longer than uname
if (count of hosts) > (count of uname) then return
repeat with i from 1 to count hosts
repeat 1 times -- simulate continue
set currentAddress to item i of hosts
set currentHostname to item i of uname
if not ((do shell script "ping -o -t 5 " & currentAddress & "&>dev/null && echo yes || echo no") as boolean) then
exit repeat -- continue
end if
tell application "Terminal"
do script "ssh " & currentHostname
end tell
end repeat
end repeat
im writting a small script for starting an 'xpra' session with a remote machine. I'm pretty new to bash scripting, so I was wondering if someone could help me clean up the code a bit, concerning best practices.
The ssh line is the one i'm having problems with, as I must CTRL-C on the keyboard for the command to be killed and let it continue to echo "done".
How can I fix that minor issue?
### ###
# syntax: xpra.sh hostmachine command #
## ###
## Wake on LAN host machine.
~/scripts/$1
## Check if online and ssh command.
## Attach xpra client.
while :; do
ping -c 1 $1
if [ $? -eq 0 ]; then
ssh $1 "xpra start :7 && sleep 2 && ("DISPLAY=:7 $2"&) ";
echo "done";
sleep 5;
echo "attaching";
(xpra attach ssh:$1:7 &);
break;
else
echo "host offline";
sleep 180s;
fi
done
Newer versions support starting remote sessions in one command, try:
xpra start ssh://HOST:SSH_PORT/DISPLAY --start-child=xterm
this will
start a new remote session on display DISPLAY
start an xterm in it
then connect your client to this session
It's a lot cleaner than a script that relies on "sleep"...
Either you want the ssh line to finish before moving to the next line, in which case what you have is correct; or you want to move on to the next line while it is still running, in which case you can append a "&" character to the line:
ssh $1 "xpra start :7 && sleep 2 && ("DISPLAY=:7 $2"&) " &
(Main comment I would make about your style is that ending all your lines with ";"'s is unnecessary, and it would be clearer if you indented the parts of your if statement.)
as Adam Liss mentioned in the comments:
ssh -f $COMMAND
will open an ssh session, ask for your credentials, then go into the background as it launches the command on the remote host.
I'm trying to achieve the following with a bash script:
try for SSH connection, if fails, error out if SSH connection is
once confirmed, execute the 'top' command and save results to file
scp file back from remote server
I know the invidiual commands, which would be:
1) to check the ssh connection:
ssh -q user#ip exit
echo $?
This should return '0' on success and '255' on error.
2) to execute top and save to file would be:
top -n 1 -b > /tmp/top.out
3) scp back file from remote host
expect -c "
set timeout 1
spawn scp user#host:/tmp/top.out root#anotherhost:/.
expect yes/no { send yes\r ; exp_continue }
expect password: { send password\r }
expect 100%
sleep 1
exit
"
Now putting this altogether is my problem, to be more specific:
I can't seem to be able to get the returned '0' and '255' values when using expect to test the SCP connection.
I can't seem to be able to execute the top command using expect again, i.e. this doesn't work:
expect -c "
set timeout 1
spawn ssh user#host top -n 3 -b > /tmp/top.out
expect password: { send password\r }
sleep 1
exit
"
and therefore the 3rd bit won't work either.
Any help is appreciated. Please bear in mind that my script is a .sh script with the #!/bin/bash declaration -- I cannot use #!/usr/bin/expect for various reasons.
Now that's ugly stuff. There are many pitfalls, probably you are not quite sure at what places you execute with a shell, or with plain argv array. Also the expect stuff is not the way that is supposed to be done, that's only brittle.
(AFAIK, expect is mainly meant to be used to communicate with modems (AT command set) and the like).
Use SSH keys for automated ssh and scp instead of passwords. Once you've done that (or even before, but then you have to enter passwords manually), launch this in your shell:
$ ssh user#server "top -n 1 -b" > /tmp/top.out
and the file will be on your local machine. (Because redirection was done locally, not yet remotely). No need to scp.
That's all there is to it.
Check this one:
https://stackoverflow.com/a/23632210/524743
expect <<'END'
log_user 0
spawn sh -c {echo hello; exit 42}
expect eof
puts $expect_out(buffer)
lassign [wait] pid spawnid os_error_flag value
if {$os_error_flag == 0} {
puts "exit status: $value"
} else {
puts "errno: $value"
}
END
hello
exit status: 42
From the expect man page
wait [args]
delays until a spawned process (or the current process if none is named) terminates.
wait normally returns a list of four integers. The first integer is the pid of the process that was waited upon. The second
integer is the corresponding spawn id. The third integer is -1 if an
operating system error occurred, or 0 otherwise. If the third integer
was 0, the fourth integer is the status returned by the spawned
process. If the third integer was -1, the fourth integer is the value
of errno set by the operating system. The global variable errorCode is
also set.