code-8
code-8

Reputation: 58730

Execute Bash script remotely via cURL

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?

Upvotes: 15

Views: 9801

Answers (3)

Dmitri Sandler
Dmitri Sandler

Reputation: 1192

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.

Upvotes: 0

Tarun Lalwani
Tarun Lalwani

Reputation: 146630

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

Upvotes: 12

glenn jackman
glenn jackman

Reputation: 247042

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 ... )

Upvotes: 17

Related Questions