15

I have a simple Bash script that takes in inputs and prints a few lines out with that inputs

fortinetTest.sh

read -p "Enter SSC IP: $ip " ip && ip=${ip:-1.1.1.1}
printf "\n"

#check IP validation
if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
  echo "SSC IP: $ip"
  printf "\n"
else
  echo "Enter a valid SSC IP address. Ex. 1.1.1.1"
  exit
fi

enter image description here

I tried to upload them into my server, then try to run it via curl

enter image description here

I am not sure why the input prompt never kick in when I use cURL/wget.

Am I missing anything?

6
  • 2
    Does it have to be a prompt? Seems like a url parameter would be simpler. Commented Apr 5, 2018 at 19:09
  • curl used via wget isn't a terminal emulator allowing prompt/response, it is a is getter of data (one way). You'll need to add the SSC IP input via the curl command (ie. curl ..sh < 1234 | bash) Commented Apr 5, 2018 at 19:12
  • @PrestonM : I don't mind use your suggestion, sound way better than what I am trying to do right now, but I'm not sure how to adjust my code to use read from URL params. wanna get me started with a few lines ? Commented Apr 5, 2018 at 19:14
  • @RandyCasburn, do you mind answer it ? you suggestion might works in term of what I am trying to do. Commented Apr 5, 2018 at 19:16
  • 2
    I don't recommend running the script directly from curl in the first place. Good security dictates you download the script first, examine it to make sure it is the script you expect, then execute it. curl ... > tmp.sh; <look at it>; bash tmp.sh. Commented Apr 5, 2018 at 19:39

3 Answers 3

17

With the curl ... | bash form, bash's stdin is reading the script, so stdin is not available for the read command.

Try using a Process Substitution to invoke the remote script like a local file:

bash <( curl -s ... )
Sign up to request clarification or add additional context in comments.

7 Comments

Very nice! That definitely addresses what I mentioned!
What happens if remote resources are required during execution?
Then downloading the script is clearly the wrong solution. You'd want ssh -t user@host 'bash script.sh'
@glennjackman - can you please give example with script or proof ? I've tried it. Not seem to work. I'm not sure what I miss.
"doesn't work" is a useless problem description. Provide details.
|
12
+25

Your issue can be simply be reproduced by run the script like below

$ cat test.sh | bash
Enter a valid SSC IP address. Ex. 1.1.1.1

This is because the bash you launch with a pipe is not getting a TTY, when you do a read -p it is read from stdin which is content of the test.sh in this case. So the issue is not with curl. The issue is not reading from the tty

So the fix is to make sure you ready it from tty

read < /dev/tty -p "Enter SSC IP: $ip " ip && ip=${ip:-1.1.1.1}
printf "\n"

#check IP validation
if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
  echo "SSC IP: $ip"
  printf "\n"
else
  echo "Enter a valid SSC IP address. Ex. 1.1.1.1"
  exit
fi

Once you do that even curl will start working

vagrant@vagrant:/var/www/html$ curl -s localhost/test.sh | bash
Enter SSC IP:  2.2.2.2

SSC IP: 2.2.2.2

1 Comment

This may or may not work in bash, but how the heck do you translate this to other languages like PHP and C++??
0

I personally prefer source <(curl -s localhost/test.sh) option. While it is similar to bash ..., the one significant difference is how processes handled.

bash will result in a new process being spun up, and that process will evoke commands from the script.
source on the other hand will use current process to evoke commands from the script.

In some cases that can play a key role. I admit that is not very often though.

To demonstrate do the following:

### Open Two Terminals
# In the first terminal run:
echo "sleep 5" > ./myTest.sh
bash ./myTest.sh

# Switch to the second terminal and run:
ps -efjh

## Repeat the same with _source_ command
# In the first terminal run:
source ./myTest.sh

# Switch to the second terminal and run:
ps -efjh

Results should look similar to this:

Before execution:

before

Running bash (main + two subprocesses):

bash

Running source (main + one subprocess):

source

UPDATE: Difference in use variable usage by bash and source:

source command will use your current environment. Meaning that upon execution all changes and variable declarations, made by the script, will be available in your prompt.

bash on the other hand will be running in as a different process; therefore, all variables will be discarded when process exits.

I think everyone will agree that there are benefits and drawbacks to each method. You just have to decide which one is better for your use case.

## Test for variables declared by the script:
echo "test_var3='Some Other Value'" > ./myTest3.sh
bash ./myTest3.sh
echo $test_var3
source ./myTest3.sh
echo $test_var3

Testing setting environment variables by the script

## Test for usability of current environment variables:
test_var="Some Value" # Setting a variable
echo "echo $test_var" > myTest2.sh # Creating a test script
chmod +x ./myTest2.sh # Adding execute permission
## Executing:
. myTest2.sh
bash ./myTest2.sh
source ./myTest2.sh
./myTest2.sh
## All of the above results should print the variable.

Testing access to environment variables with different execution methods.

I hope this helps.

3 Comments

An issue with sourcing scripts instead of running them in a subprocess is that the script can alter your invoking (interactive) shell's environment. (e.g. mess with your PATH, change the prompt, set unexpected options, modify shell variables, set signal handlers, etc)
@GertvandenBerg, Have you ran into such situation and were you able to reproduce it? I haven't encountered such behaviour, which is why I don't believe it to be the case. I will update my answer with example.
A quick sample would be echo PS1=test > test.sh; bash test.sh # no change to prompt in shell that called the script source test.sh # changes the calling shell's prompt. (source is meant for this type of thing...)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.