Invoking a process whenever someone logins through SSH - ruby

I'm trying to invoke a ruby script whenever anyone tries to SSH into the server(say Ubuntu 14.04).
Like for example someone is trying to login with ssh root#serverip and my ruby script should be called upon and the login process should continue only if the script returns true and if returns false the connection should be closed.
How can I achieve this?
Thanks.

To fulfill your requirements, you should also work with $SSH_ORIGINAL_COMMAND environment variable, if you use ForceCommand option:
ForceCommand /path/to/script && $SSH_ORIGINAL_COMMAND
This will run your script and based on the exit status of the /path/to/script, it will run the user command or exit session.

You can try using the ForceCommand parameter in the sshd_config file of your server. it's fairly straightforward and well documented online :)
You enter at the bottom of the config file:
ForceCommand /path/to/script
Not so sure if you can check for certain conditions and terminate the connection, however this might guide you.

As mentioned by a friend in an answer, exit code based execution didn't work for me.
Here's a workaround :-
As mentioned by some folks, I used this in /etc/ssh/sshd_config
ForceCommand /path/to/script
Then in the script I opened the bash if they satisfied certain conditions. For example in bash
#!/bin/bash
if [ condition ]
then
bash #This will open bash if condition is satisfied.
//login
fi
Thanks everyone!

Related

Run local bash script on remote host

I have this bash script that opens a terminal repeatedly with no way of closing them and keeps one after another. The goal is annoy anyone who happens to execute this program. Here's the source code of it:
#!/bin/bash
while true
do
gnome-terminal -x sh -c "./<name-of-script.sh>; bash"
clear
sleep 1
trap '' 2
exit
done
I have tested this and it does work the way I want it to. What I'm trying to do is execute this script on a remote host. On a ruby on rails website I have set an image to attempt to run this script by clicking on it. When someone does they will run a controller function called call_script2 and here's what I have so far:
def call_script2
remote_ip = request.ip
#system("scp /home/ncs/<script.sh> root##{remote_ip}:/root/")
system("ssh root##{remote_ip} sudo home/ncs/./<script.sh>")
render 'script/index'
end
What I'm trying to accomplish is to run the contents of the bash script on the remote host when they click on a certain image. As you can see I've tried uploading the script of the host under the root directory and then trying to run the bash program with no success. I'm perfectly fine using something other than SSH if this not do able.
Please feel free to share your thoughts on this and thank you for taking the time to read my post. Have a great day!
Update: I was able to accomplish this goal by using the following:
system("ssh -t root##{remote_ip} DISPLAY=:0 ./Thorgrim.sh")
Thank you to everyone who have commented on this post to help me out!

issue executing shell script

I'm having a strange issue when I try and execute a shell script.
when I try to execute the script with ./scriptname.sh it just immediately returns to the prompt. The script has the correct permissions set. If I copy the script to another server it executes no problem at all.
I can execute other sh scripts on the server in question with no problem.
is there a way of troubleshooting this as I am at a loss?
Thanks in advance.
Best way to check the syntax errors, you can do the below.
sh -n script_name
If you wanted to execute the script and see the flow you can use the below
sh -x script_name
Hope it helps

Laravel Envoy and bash prompt

I'm using Envoy to provision a remote server. Provisioning is done by pulling the bash script from a private repo and then execute it.
The bash script ask some confirmation like yes/no (using bash "read -p"): it works as expected when i'm connected to the remote server... the script wait for user input.
Instead Envoy seems to ignore any prompt. Is it an expected behavior?
Any workaround?
Yes, this is expected. There's nothing for read to read from so it doesn't.
You have a few options.
Rewrite your script to use a config file when there's no terminal to prompt from.
Use something like [ -t 0 ] to test if the standard input is a terminal and load a configuration file with defaults. The simplest way to do that is just have a file that contains appropriate variable assignments and just source it . defaults.sh or whatever. You don't even need the -t test if you source the defaults first since then anything the user inputs will over-ride the default value.
Rewrite your script to have sane defaults.
Rewrite whatever runs the script to provide your script input via pipeline/file via redirection (e.g. printf 'answer 1\nanswer 2\n' | ./script.sh or ./script.sh <answerfile).

FTP inside a shell script not working

My host upgraded my version of FreeBSD and now one of my scripts is broken. The script simply uploads a data feed to google for their merchant service.
The script (that was working prior to the upgrade):
ftp ftp://myusername:mypassword#uploads.google.com/<<END_SCRIPT
ascii
put /usr/www/users/myname/feeds/mymerchantfile.txt mymerchantfile.txt
exit
END_SCRIPT
Now the script says "unknown host". The same script works on OSX.
I've tried removing the "ftp://". - No effect
I can log in from the command line if I enter the username and password manually.
I've search around for other solutions and have also tried the following:
HOST='uploads.google.com'
USER='myusername'
PASSWD='mypassword'
ftp -dni <<END_SCRIPT
open $HOST
quote USER $USER
quote PASS $PASS
ascii
put /usr/www/users/myname/feeds/mymerchantfile.txt mymerchantfile.txt
END_SCRIPT
And
HOST='uploads.google.com'
USER='myusername'
PASSWD='mypassword'
ftp -dni <<END_SCRIPT
open $HOST
user $USER $PASS
ascii
put /usr/www/users/myname/feeds/mymerchantfile.txt mymerchantfile.txt
END_SCRIPT
Nothing I can find online seems to be doing the trick. Does anyone have any other ideas? I don't want to use a .netrc file since it is executed by cron under a different user.
ftp(1) shows that there is a simple -u command line switch to upload a file; and since ascii is the default (shudder), maybe you can replace your whole script with one command line:
ftp -u ftp://username:password#uploads.google.com/mymerchantfile.txt\
/usr/www/users/myname/feeds/mymerchantfile.txt
(Long line wrapped with \\n, feel free to remove the backslash and place it all on one line.)
ftp $HOSTNAME <<EOFEOF
$USER
$PASS
ascii
put $LOCALFILE $REMOTETEMPFILE
rename $REMOTETEMPFILE $REMOTEFINALFILE
EOFEOF
Please note that the above code can be easily broken by, for example, using spaces in the variables in question. Also, this method gives you virtually no way to detect and handle failure reliably.
Look into the expect tool if you haven't already. You may find that it solves problems you didn't know you had.
Some ideas:
just a thought since this is executed in a subshell which should inherit correctly from parent, does an env show any difference when executed from within the script than from the shell?
Do you use a correct "shebang"?
Any proxy that requires authentication?
Can you ping the host?
In BSD, you can create a NETRC script that ftp can use for logging on. You can even specify the NETRC file in your ftp command too using the -N parameter. Otherwise, the default NETRC is used (which is $HOME/.netrc).
Can you check if there's a difference in the environment between your shell-login, and the cron-job? From your login, run env, and look out for ftp_proxy and http_proxy.
Next, include a line in the cron-job that will dump the environment, e.g. env >/tmp/your.env.
Maybe there's some difference...Also, did you double-check your correct usage of the -n switch?

Auto SSH and execute script

I have roughly 12 computers that each have the same script on them. This script merely pings all the other machines, and prints out whether the machine is "reachable" or "unreachable". However, it is inefficient to login to each machine manually using ssh to execute this script.
Suppose I'm logged into node 1. Is there any way to for me to login to node 2-12 automatically using SSH, execute the ping script, pipe the results to a file, logout and proceed to the next machine? Some kind of bash shell script?
I'm afraid I'm at a loss here since I haven't had experience with shell-scripting before.
Since the script is on the other machines, you can just have ssh run the command for you there:
ssh $hostname my_script >> results_file
When you specify a command like that, it's executed instead of the login shell.
I'll leave it up to you to figure out how to loop over hostnames!
One trick you'll need to use is setting up pre-authorized keys for each host. Then you can run a script on one host, running something like 'ssh hostname command > log.hostname'
This script might be what you are looking for: It allows you to execute one command (which can be your script) on multiple remote machines via ssh. It's a simple script with bash source available, so you should be able to customize it to your needs:
http://www.heinzi.at/projects/upgradebest.sh/
Yes you can
You need actually 2 small scripts as following:
remote_ssh.sh ( which takes as first argument the name of the machine and the rest of the arguments are your script that you want to execute with his own arguments)
Example : remote_ssh.sh node5 "echo hello world"
remote_ssh.sh as following:
#!/bin/bash
ALL_ARG=$#
FST_ARG=$1
REST_ARG=${ALL_ARG##$FST_ARG}
echo "Executing REMOTE COMMAND ON $FST_ARG"
/usr/bin/ssh $FST_ARG bash execute_ssh_command.sh $FST_ARG pwd $REST_ARG
execute_ssh_command.sh as following :
#!/bin/bash
ALL_ARG=$#
FST_ARG=$1
DIR_ARG=$2
REM_ARG="$1 $2"
REST_ARG=${ALL_ARG##$REM_ARG}
cd $DIR_ARG
$REST_ARG
of course you have to get this 2 scripts in your path of all your nodes ( maybe ~/bin/ )
Hope that it's helpful

Resources