I want to log into server based on user's choice so I wrote bash script. I am totally newbie - it is my first bash script:
#!/bin/bash
echo -e "Where to log?\n 1. Server A\n 2. Server B"
read to_log
if [ $to_log -eq 1 ] ; then
echo `ssh user#ip -p 33`
fi
After executing this script I am able to put a password but after nothing happens.
If someone could help me solve this problem, I would be grateful.
Thank you.
The problem with this script is the contents of the if statement. Replace:
echo `ssh user#ip -p 33`
with
ssh user#ip
and you should be good. Here is why:
Firstly, the use of back ticks is called "command substitution". Back ticks have been deprecated in favor of $().
Command substitution tells the shell to create a sub-shell, execute the enclosed command, and capture the output for assignment/use elsewhere in the script. For example:
name=$(whoami)
will run the command whoami, and assign the output to the variable name.
the enclosed command has to run to completion before the assignment can take place, and during that time the shell is capturing the output, so nothing will display on the screen.
In your script, the echo command will not display anything until the ssh command has completed (i.e. the sub-shell has exited), which never happens because the user does not know what is happening.
You have no need to capture the output of the ssh command, so there is no need to use command substitution. Just run the command as you would any other command in the script.
Related
I don't understand why the the read prompt and the answer are not displayed in that use case :
bash-4.3.30$ bash -i <<< 'read -p prompt
answer
echo $REPLY'
I would have expected the words "prompt" & "answer" to be displayed. But instead, I obtain that:
sylvain#bulbizarre:~$ read -p prompt
sylvain#bulbizarre:~$ echo $REPLY
answer
sylvain#bulbizarre:~$ exit
FWIW, this is an mcve. I understand out-of-context this can seem stupid. But I really want to feed an interactive shell with some commands and observe a behavior very similar to a real interactive session.
From the documentation:
-p prompt
Display prompt, without a trailing newline, before attempting to read any input. The prompt is displayed only if input is coming from a terminal.
When you use a here-doc or here-string, input is coming from a pipe, not a terminal, so the prompt isn't displayed.
You can solve this by using Expect to automate execution of the command, instead of redirecting input.
I have a script I want to run on remote via ssh. It checks if there is a process running and should try to kill it, if it exists. Now, my code looks like this:
ssh my_prod_env << ENDSSH
...
pid=$(pgrep -f "node my_app.js")
echo $pid
# kill process with $pid
...
exit
ENDSSH
The problem lies here: I cannot capture output of pgrep command in variable. I tried with $(), backticks, pipe then read and maybe other approaches, but all without success.
I would like to do it all in one ssh session.
Now I am thinking the output of command goes to the output stream I cannot access in my script. I might be wrong, though.
Either way, help will be appreciated.
Ok, after you provided in comments more info what you want, I believe this is the correct answer to your question:
ssh my_prod_env -t 'pgrep -f "node my_app.js"'
This will call the command and leave you logged on the server
This is what fixes the thing - "escaping" the ENDSSH tag.
ssh my_prod_env << /ENDSSH
...
# capture output of remote commands in remote variables
...
ENDSSH
Problem was that my vars were local and I was trying to capture output of remote commands in them.
This question/answer helped me realize what is going on: How to assign local variable with a remote command result in bash script?
So, my question could be marked as duplicate or something similar, I guess.
I am passing variable from one shell script to another which is being executed on another remote server.
Script 1
echo "Identification No."
read id
export id
ssh atul#10.95.276.286 'bash -s' < data_file.sh
Script 2
echo "ID is ---- "$id
cd /abc/xyz/data/
cat data_abcxyz.txt|grep '|$id|'|wc -l
By this way I am not able to get any output even the id is also null in the second script.
I have also tried
ssh atul#10.95.276.286 'bash -s' < data_file.sh "$id"
But got no output.
Any help on this is greatly appreciated. I am using unix AIX.
export on one host is absolutely not going to affect an entirely different host... it doesn't even affect another shell running on the current host.
Your second attempt is better and might even work if your script were checking for positional arguments but it isn't. (It might not even work in that case as I'm not at all sure that the command line argument would make it through to the script through ssh and bash -s.
You might be able to do something more like:
ssh atul#10.95.276.286 "bash -s $id" < data_file.sh
to pass the argument to the remote bash directly but your script would still need to use positional arguments and not expecting named variables to already exist.
Exporting won't have any effects on the environment of remote scripts.
You can set up a remote script's environment by specifying the env variables on the command line before the actual command, which you can btw use for local commands too.
ssh atul#10.95.276.286 "id=$id bash -s" < data_file.sh
If you pass "$id" this way:
ssh atul#10.95.276.286 'bash -s' < data_file.sh "$id"
It'll be your script's first parameter, AKA "$1" and you'll be able to access it from your script that way.
Note that '|$id|' in your "Script 2" will be interpreted as a literal string, since you're using single quotes.
I am running a bash script that takes hours. I was wondering if there is way to monitor what is it doing? like what part of the script is currently running, how long did it take to run the whole script, if it crashes at what line of the script stopped working, etc. I just want to receive feedback from the script. Thanks!!!
from man page for bash,
set -x
After expanding each simple command, for command, case command, select command, or arithmetic for command, display the expanded value of PS4, followed by the command and its expanded arguments or associated word list.
add these to the start of your script,
export PS4='+{${BASH_SOURCE}:$LINENO} '
set -x
Example,
#!/bin/bash
export PS4='+{${BASH_SOURCE}:$LINENO} '
set -x
echo Hello World
Result,
+{helloworld.sh:6} echo Hello World
Hello World
Make a status or log file. For example add this inside your script:
echo $(date) - Ok >> script.log
Or for a real monitoring you can use strace on linux for see system call, example:
$ while true ; do sleep 5 ; done &
[1] 27190
$ strace -p 27190
In my bash script, I do:
ssh me9#some_mad_server.com;
cd ~/apple;
echo "Before Exit"
exit
echo "After Exit"
I never see Before Exit or After Exit. I can understand why I may not see Before Exist as my script at that stage is in another console. But I am confused if the Exit mean my script ends and hence why After Exit never gets logged.
Any help appreciated.
To execute a series of commands on a remote host, you need to pass them to ssh on the command line, not execute them after the ssh call. Like this:
ssh me9#some_mad_server.com '
cd ~/apple
echo "Before Exit"
'
echo "After Exit"
This uses a multiline string to pass multiple commands. An exit is implicit when the end of the string is reached.
Importantly, the commands in the quoted string are executed on the remote host, while the final echo is executed on the local server. I've indented the remote commands for clarity.
You can use screen for this.
screen -d -m <command>
Use screen -r to attach to that screen again
screen -r <screen ID>