How to Run a Bash Script in Linux

By 

Updated on

6 min read

Run Bash Shell Script

If you use Linux, learning to run bash scripts is an important skill. Bash scripts help you automate tasks, manage your system, and make your work easier. There are several ways to execute a bash script, and the best method depends on what you need.

This article explains the different methods for running and executing bash scripts in Linux and how to resolve common issues. If you are new to Linux, start with our guide on basic Linux commands .

Quick Reference

For a printable quick reference, see the Bash cheatsheet .

MethodCommandWhen to use
Executable./script.shStandard run after chmod +x
Bash interpreterbash script.shNo permission change needed
With arguments./script.sh arg1 arg2Pass input to the script
Sourcesource script.sh or . script.shApply variables and functions to current shell
Background./script.sh & or nohup ./script.sh &Long-running tasks
Debugbash -x script.shTrace each command before it runs

Making a Script Executable

The most common way to run a bash script is to make it executable and run it directly.

First, at the top of your script, add a shebang line that tells the system which interpreter to use:

script.shsh
#!/bin/bash

echo "Hello, World!"
Warning
The shebang must be on the first line of the file.

Use chmod to make the script executable:

Terminal
chmod +x script.sh

Now run the script by typing ./ followed by the script name:

Terminal
./script.sh
output
Hello, World!

The ./ tells the shell to look for the script in the current directory.

Running a Script with the Bash Interpreter

You can run a script by explicitly calling the bash interpreter. This method does not require the script to be executable:

Terminal
bash script.sh

This is handy if you cannot change file permissions or want to test a script quickly.

You can also start a script with sh, but only when the script sticks to POSIX syntax:

Terminal
sh script.sh

On Debian, Ubuntu, and their derivatives, /bin/sh is a symlink to dash, a smaller shell that does not understand Bash-specific syntax. A Bash script started with sh fails on constructs such as [[ ... ]] and arrays:

output
script.sh: 1: [[: not found

When in doubt, use bash. It matches the shebang that the script already declares.

Passing Arguments to a Script

Any words you type after the script name are handed to the script as arguments. This works with every method shown so far:

Terminal
./script.sh alice 42

Inside the script, the arguments are available as $1, $2, and so on, while $@ holds all of them at once:

greet.shsh
#!/usr/bin/env bash

echo "First argument: $1"
echo "Second argument: $2"
echo "All arguments: $@"

Run it with two arguments:

Terminal
./greet.sh alice 42
output
First argument: alice
Second argument: 42
All arguments: alice 42

Notice that the script name is missing from that list. It lives in $0, so user arguments start counting at $1. For flags, defaults, and validation, see our guide on passing arguments to a bash script .

Sourcing a Script (Run in the Current Shell)

Sourcing a script runs it in the current shell session, not in a subshell. Use the source command or its shorthand .:

Terminal
source script.sh

Or:

Terminal
. script.sh

This is useful when the script sets environment variables or defines functions that you want to use in your current shell.

For example, if you have a script that sets a variable:

setenv.shsh
#!/bin/bash
export MY_VAR="Hello"

When running normally, the variable is not available in the current shell:

Terminal
./setenv.sh
echo $MY_VAR

The command prints no output because the variable is set only inside the child process.

When sourcing, the variable persists:

Terminal
source setenv.sh
echo $MY_VAR
output
Hello

Running Scripts in the Background

To run a script in the background , append & to the command:

Terminal
./script.sh &

For long-running scripts that should continue after you log out, use nohup :

Terminal
nohup ./script.sh &

Checking the Exit Status

Every script returns an exit status when it finishes. A status of 0 means success, and anything from 1 to 255 signals an error. The special variable $? holds the status of the last command that ran:

Terminal
./script.sh
echo $?
output
0

This matters most in automation, where a wrapper script or a scheduled job decides what to do next based on whether your script succeeded. Set the status explicitly with exit :

check.shsh
#!/usr/bin/env bash

if [[ ! -f /etc/passwd ]]; then
  exit 1
fi

exit 0

Every command overwrites $?, including echo. If you need the status later, copy it into a variable on the line right after the script runs.

Running Scripts with Debug Mode

To debug a script and see each command before it executes, use the -x flag:

Terminal
bash -x script.sh
output
+ echo 'Hello, World!'
Hello, World!

Other useful Bash flags include:

  • bash -n script.sh - Check syntax without running
  • bash -v script.sh - Print lines as they are read
  • bash -e script.sh - Exit immediately on error

Running Scripts from Anywhere

To run a script from any directory, you can either specify the full path or add the script to a directory in your $PATH .

A common approach is to create a ~/bin directory:

Terminal
mkdir -p ~/bin

Add it to your ~/.bashrc:

Terminal
export PATH="$HOME/bin:$PATH"

Move your script there and make it executable:

Terminal
mv script.sh ~/bin/
chmod +x ~/bin/script.sh

After reloading your shell or running source ~/.bashrc, you can run the script from anywhere:

Terminal
script.sh

Using /usr/bin/env in the Shebang

Instead of hardcoding the Bash path, you can use:

script.shsh
#!/usr/bin/env bash

echo "Hello, World!"

This approach is considered best practice because it works across different systems and respects the user’s environment.

Troubleshooting

Permission Denied

output
bash: ./script.sh: Permission denied

Make the script executable:

Terminal
chmod +x script.sh

Command Not Found

output
bash: script.sh: command not found

Use ./ prefix or provide the full path:

Terminal
./script.sh

Bad Interpreter

output
bash: ./script.sh: /bin/bash^M: bad interpreter: No such file or directory

The file has Windows line endings, so the shebang reads as /bin/bash followed by a carriage return. Strip them with sed:

Terminal
sed -i 's/\r$//' script.sh

If dos2unix is installed, it does the same job:

Terminal
dos2unix script.sh

Syntax Error When Using sh

output
script.sh: 1: Syntax error: "(" unexpected

The script uses Bash syntax but was started with sh, which is dash on Debian and Ubuntu. Run it with bash script.sh or ./script.sh instead.

Security Considerations

  • If you downloaded a script from the Internet, always check its contents before running it.
  • Be extra careful when running scripts as root.
  • Use restrictive permissions when you can.
  • Do not add the current directory (.) to $PATH.
  • Do not run a script unless you are sure it is safe.

Conclusion

A practical workflow is to keep your scripts in ~/bin, make them executable with chmod +x, and start each one with #!/usr/bin/env bash. Reach for source only when a script needs to set variables or define functions in your current shell.

Next, learn how to write your own with our guide on bash functions .

Tags

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page