I'm trying to execute this command on a remote computer using ssh.
ssh user#host "if [ $(ls -la /folder | wc -l) -eq 83 ]; then true; else false; fi;"
How can I make this part $(ls -la /folder | wc -l) to be executed on the remote computer instead of locally?
To prevent $() from being expanded locally, put it in single quotes:
ssh user#host 'if [ $(ls -la /path | wc -l) -eq 83 ]; then true; else false; fi;'
But you don't need the if/else, just do:
ssh user#host '[ $(ls -la /path | wc -l) -eq 83 ]'
Related
I have a VPN connection in MacOS BigSur but I can't access it inside a Linux VM running under VMWare Fusion V12.1.2.
The issue has been fixed in V12.2.0 VMWare Fusion 12.2.0 Release Notes
The solution is to manually create the VPN tunnel and link it to the VM as there are multiple commands involved and the IP Address can change I created the following script to execute the required commands.
#!/bin/bash
function ask_yes_or_no() {
read -p "$1 ([y]es or [N]o): "
case $(echo $REPLY | tr '[A-Z]' '[a-z]') in
y|yes) echo "yes" ;;
*) echo "no" ;;
esac
}
currNatRules=$(sudo pfctl -a com.apple.internet-sharing/shared_v4 -s nat 2>/dev/null)
if test -z "$currNatRules"
then
echo -e "\nThere are currently no NAT rules loaded\n"
exit 0
fi
utunCheck=$(echo $currNatRules | grep utun)
if test -n "$utunCheck"
then
echo -e "\nIt looks like the VPN tunnel utun2 has already been created"
echo -e "\n$currNatRules\n"
if [[ "no" == $(ask_yes_or_no "Do you want to continue?") ]]
then
echo -e "\nExiting\n"
exit 0
fi
fi
natCIDR=$(echo $currNatRules | grep en | grep nat | cut -d\ -f 6)
if test -z "$natCIDR"
then
echo -e "\nCannot extract the NAT CIDR from:"
echo -e "\n$currNatRules\n"
exit 0
fi
interface=$(route get 10/8 | grep interface | cut -d\ -f 4)
echo -e "\nNAT CIDR=$natCIDR Interface=$interface\n"
newRule="nat on ${interface} inet from ${natCIDR} to any -> (${interface}) extfilter ei"
echo -e "\nAdding new rule: $newRule\n"
configFile="fixnat_rules.conf"
[[ -d $configFile ]] && rm $configFile
echo "$currNatRules" > $configFile
echo "$newRule" >> $configFile
sudo pfctl -a com.apple.internet-sharing/shared_v4 -N -f ${configFile} 2>/dev/null
echo -e "\nConfig update applied\n"
sudo pfctl -a com.apple.internet-sharing/shared_v4 -s nat 2>/dev/null
echo -e "\n"
exit 0
I use the kitty terminal emulator, so when I connect to a new server, I (usually) need to ad the terminfo (at least, this way it seems to work). To do this I wrote a script. While I was at it, I added a bit of code to add a public key if the user wants it to.
Not really relevant for the question, but here is the code:
#!/bin/bash
host=$1
ip=$(echo $host | cut -d# -f2 | cut -d: -f1)
# Check if it is a unknown host
if [[ -z $(ssh-keygen -F $ip) ]]; then
# Check if there are any ssh-keys
if [ $(ls $HOME/.ssh/*.pub > /dev/null | wc -l) -ne 0 ]; then
keys=$(echo $( (cd $HOME/.ssh/ && ls *.pub) | sed "s/.pub//g" ))
ssh -q -o PubkeyAuthentication=yes -o PasswordAuthentication=no $host "ls > /dev/null 2>&1"
# Check if the server has one of the public keys
if [ $? -ne 0 ]; then
echo "Do you want to add a SSh key to the server?"
while true; do
read -p " Choose [$keys] or leave empty to skip: " key
if [[ -z $key ]]; then
break
elif [[ -e $HOME/.ssh/$key ]]; then
# Give the server a public key
ssh $host "mkdir -p ~/.ssh && chmod 700 ~/.ssh && echo \"$(cat $HOME/.ssh/$key.pub)\" >> ~/.ssh/authorized_keys"
break
else
echo "No key with the name \"$key\" found."
fi
done
fi
fi
# Copy terminfo to server
ssh -t $host "echo \"$(infocmp -x)\" > \"\$TERM.info\" && tic -x \"\$TERM.info\" && rm \$TERM.info"
fi
It is not the best code, but it seems to work. Tips are ofcourse welcome.
The problem is that I need to run this script every time I connect te a new remote server (or I need to keep track of which server is new, but that is even worse). Is there a way to run this script every time I connect to a server (the script checks if the ip is a known host).
Or is there an other way to do this? Adding the public keys is nice to have, but not very important.
I hope somone can help,
Thanks!
There is a trick to identify that you are using ssh to login on the target machine:
pgrep -af "sshd.*"$USER |wc -l
The above command will count the user's processes using sshd
You can add the above command in the target machine, to test if you are connected via ssh. Add the above command to your .profile or .bash_profile script in the target machine.
So that only if you login via ssh your script will run initiation script on the target machine when you login/connect.
Sample .bash_profile on target machine
#!/bin/bash
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
if [[ $(pgrep -af "sshd.*"$USER |wc -l) -gt 0 ]]; then
your_init_script
fi
I try to connect to the remote server by ssh and execute the command.
But given the situation, I can only execute a single command.
For example
ssh -i ~/auth/aws.pem ubuntu#server "echo 1"
It works very well, but I have a problem with the following
case1
ssh -i ~/auth/aws.pem ubuntu#server "cd /"
ssh -i ~/auth/aws.pem ubuntu#server "ls"
case2
ssh -i ~/auth/aws.pem ubuntu#server "export a=1"
ssh -i ~/auth/aws.pem ubuntu#server "echo $a"
The session is not maintained.
Of course, you can use "cd /; ls"
but I can only execute one command at a time.
...
Reflecting comments
developed a bash script
function cmd()
{
local command_delete="$#"
if [ -f /tmp/variables.current ]; then
set -a
source /tmp/variables.current
set +a
cd $PWD
fi
if [ ! -f /tmp/variables.before ]; then
comm -3 <(declare | sort) <(declare -f | sort) > /tmp/variables.before
fi
echo $command_delete > /tmp/export_command.sh
source /tmp/export_command.sh
comm -3 <(declare | sort) <(declare -f | sort) > /tmp/variables.after
diff /tmp/variables.before /tmp/variables.after \
| sed -ne 's/^> //p' \
| sed '/^OLDPWD/ d' \
| sed '/^PWD/ d' \
| sed '/^_/ d' \
| sed '/^PPID/ d' \
| sed '/^BASH/ d' \
| sed '/^SSH/ d' \
| sed '/^SHELLOPTS/ d' \
| sed '/^XDG_SESSION_ID/ d' \
| sed '/^FUNCNAME/ d' \
| sed '/^command_delete/ d' \
> /tmp/variables.current
echo "PWD=$(pwd)" >> /tmp/variables.current
}
ssh -i ~/auth/aws.pem ubuntu#server "cmd cd /"
ssh -i ~/auth/aws.pem ubuntu#server "cmd ls"
What better solution?
$ cat <<'EOF' | ssh user#server
export a=1
echo "${a}"
EOF
Pseudo-terminal will not be allocated because stdin is not a terminal.
user#server's password:
1
In this way you will send all commands to ssh as a single file script, so you can put any number of commands. Please note the way to use EOF between single quote '.
I have a script in FreeBSD 10.1 release, it's purpose is to monitor another process and keep the process alive.
When I try to kill itself, it always fail.
I try killall [name | pid]; pkill -9 [name]; service watchtas stop, none of them work.
Below is my script, please advise the solution.
#!/bin/sh
. /etc/rc.subr
prog="Thin-Agent WatchDog"
TAS_BIN="/etc/supermicro/tas-freebsd.x86_64"
TAS_LOG="/etc/supermicro/tas_system_crush.log"
monitor=1
name="watchtas"
rcvar=${name}_enable
command=/etc/rc.d/{$name}
start_cmd="watchdog"
stop_cmd="stop_watching"
load_rc_config $name
recover_tas() {
$TAS_BIN -agent start-service
RETVAl=$?
return $RETVAL
}
stop_watching() {
monitor=0
}
watchdog() {
while [ $monitor == 1 ]
do
tas_count=`ps -x | grep tas-freebsd.x86_64 | grep -v grep | wc -l | sed 's/ *//g'`
if [ $tas_count -eq 0 ]; then
timestamp=`date`
echo "[$timestamp]TAS shutdown unexpectedly, restarting TAS now..." >> $TAS_LOG
echo $?
recover_tas
else
sleep 10
fi
done
}
run_rc_command "$1"
Your start-up script fails in a couple of respects. service watchtas start does not return to the command line because the daemon process does not detach. service watchtas stop does not work as required because the variable monitor is local to the executing script.
I would separate the start-up script and the watchdog code into separate files and use daemon(8) to monitor the watchdog.
The /usr/local/etc/rc.d start-up script would look like this:
#!/bin/sh
. /etc/rc.subr
name="watchtas"
rcvar=${name}_enable
pidfile="/var/run/${name}.pid"
command="/usr/sbin/daemon"
command_args="-c -f -P ${pidfile} -r /usr/local/sbin/${name}"
load_rc_config $name
run_rc_command "$1"
The /usr/local/sbin/watchtas watchdog code would look something like this:
#!/bin/sh
TAS_BIN="/etc/supermicro/tas-freebsd.x86_64"
TAS_LOG="/etc/supermicro/tas_system_crush.log"
recover_tas() {
$TAS_BIN -agent start-service
RETVAl=$?
return $RETVAL
}
while true
do
tas_count=`ps -x | grep tas-freebsd.x86_64 | grep -v grep | wc -l | sed 's/ *//g'`
if [ $tas_count -eq 0 ]; then
timestamp=`date`
echo "[$timestamp]TAS shutdown unexpectedly, restarting TAS now..." >> $TAS_LOG
echo $?
recover_tas
else
sleep 10
fi
done
It seems you have a daemon watching a daemon watching a daemon.
I have a shell script to do the following things
sudo as a user (johnsmith) and perform few things
Exit from that user and check url status
If status is not equal to 1 , ssh to one more server and execute a
script.
But when I am running it, the lines inside 'ENDBASH' are not getting executed at all.
#!/bin/ksh
echo "Outside ENDBASH ${###*/}"
sudo -u johnssmith bash <<'ENDBASH'
echo "Inside ENDBASH ${###*/}"
#Obtaining the new version file
for file in "${###*/}"
do
if echo "$file" | grep -E "abc_cde_efg"; then
echo "Version found: $file"
else
echo "Version not found"
fi
done
exit
ENDBASH
urlArray=('http://server:port/servicename1/services/servicename1?wsdl' 'http://server:port/servicename2/services/servicename2?wsdl')
status=0
for url in "${urlArray[#]}"
do
result=`curl -s $url`
if (echo $result | grep '<?xml' >/dev/null 2>&1); then
service=$(echo $url | cut -d"/" -f4)
echo "$service is Running"
else
service=$(echo $url | cut -d"/" -f4)
echo "$service is not Running"
status=1
fi
done
if [ $status != 1 ] ; then
ssh -t username#hostname /home/dev_was/test1.sh
fi
You need to explicitly pass the arguments received by your script to the internal script:
sudo -u johnssmith bash -s "$#" <<'ENDBASH'