How To Run Sh File In Linux

How To Run Sh File In Linux

Reading time1 min
#Linux#Automation#Scripting#ShellScript#Bash#Shell

How To Run .sh Files in Linux: A Practical Engineer’s Guide

Automate or stagnate. Shell scripting isn’t optional in modern Linux administration or DevOps. But just slapping bash script.sh on every workload only covers the basics. Real-world command execution brings permissions, interpreter mismatches, subtle environment quirks, and risk—all factors you ignore at your peril.


What’s a .sh File Really?

A .sh file is simply a POSIX shell script—plain text, usually Bash- or sh-compatible, containing commands run line by line. It can automate user onboarding, orchestrate builds, or clean temp directories nightly via cron. The only requirement: the commands must be interpretable by the designated shell.


Validate First: Always Inspect the Script Content

Blind execution is occasionally disastrous. Before running anything:

cat script.sh
# or, for colorized context:
less -N script.sh
# quick edit (nano/vim/emacs based on your comfort)
nano script.sh

Review all third-party scripts, especially those pulled from forums or Stack Overflow. Shell scripts frequently embed rm, curl|bash, or worse—backdoors.


Set Proper Permissions

Unix file permissions determine security and behavior; ignore at your own risk.

ls -l script.sh

Typical permission readout:

-rw-r--r-- 1 alex devs 216 May 29 19:17 script.sh

If there’s no x (executable), you must add it:

chmod +x script.sh

Re-check:

-rwxr-xr-x 1 alex devs 216 May 29 19:17 script.sh

Note: If you’re scripting on mounted network drives (e.g., within a Docker bind-mount), you may encounter odd permission enforcement depending on NFS or CIFS flags.


Two Primary Execution Methods

1. Directly via Shell Interpreter

bash script.sh
# or
sh script.sh
  • This method ignores the file’s executable bit—permissions don’t matter as long as the shell can read the file.
  • Useful when you need to specify the shell explicitly (e.g., differences between /bin/bash and /bin/sh).
  • Practical detail: Some scripts will only work with Bash due to arrays, process substitution (<(cmd)), etc. Running with sh on Debian/Ubuntu (dash) will silently break those.

2. Execute as Standalone Program

./script.sh
  • Requires execute bit set (chmod +x).
  • Script must start with a correct shebang line—first line must be, e.g.,
    #!/bin/bash
    
  • If you omit the shebang or use a wrong path (for example, Mac’s /bin/bash vs some Linuxes’ /usr/bin/bash), expect cryptic “bad interpreter: No such file or directory” errors.

Known Gotcha: The current directory (.) is often not part of $PATH for security reasons, hence ./script.sh instead of just script.sh. Editing your $PATH to include . is discouraged outside of controlled development sandboxes.


About Shebangs: Subtle, Crucial

The shebang (#!) declares the interpreter. Three commonly used patterns:

#!/bin/bash            # Hardwired, standard in many distros; not everywhere.
#!/usr/bin/env bash    # Portable, defers lookup to whoever is first in PATH.
#!/bin/sh              # Generic shell, but not always Bash.

Compatibility issue: On Ubuntu, /bin/sh points to Dash—a fast shell with reduced features. Many scripts written for Bash will throw subtle errors:

script.sh: 7: Syntax error: "(" unexpected

Creating a Minimal Script (And a Real Example)

nano cleanup_tmp.sh

Content:

#!/usr/bin/env bash
set -e  # fail on error, critical for cron jobs

echo "Purging /tmp files older than 72 hours"
find /tmp -type f -mtime +3 -delete

Make executable:

chmod +x cleanup_tmp.sh

Run:

./cleanup_tmp.sh

Side Note: On Ubuntu 22.04’s default Bash 5.1.16, set -e catches nonzero return codes, but won’t halt on failed pipes unless you add set -o pipefail.


Passing Arguments

Scripts often require parameters. Call with:

./deploy.sh staging myapp

Inside deploy.sh, these map to $1, $2, etc.

Example:

#!/bin/bash
env="$1"
application="$2"

echo "Deploying $application to $env"

Non-obvious tip: Wrap arguments in double quotes to handle spaces, i.e. "$1". Otherwise, files or app names with whitespace break.


Debugging Shell Scripts: Beyond echo

Bugs propagate fast in automation. Tactics:

  • Enable debugging output:
    Add near the script top:
    set -x
    
    Or, run with:
    bash -x script.sh
    
    This yields trace output for every command, example:
    + echo 'Purging /tmp files older than 72 hours'
    
  • Syntax check only:
    bash -n script.sh
    
  • Log checkpoints:
    Use echo or better, logger to send to syslog:
    logger "Starting cleanup at $(date)"
    

Practical issue: Large scripts with many subshells or background processes (&) become unwieldy to debug with just set -x. In those cases, sprinkle trap lines:

trap 'echo "Error at line $LINENO"; exit 1' ERR

Environment and Sourcing Pitfalls

Each invocation with ./script.sh launches a separate process. Environment variables exported in your interactive shell are only visible in scripts if you export them:

MY_ENV=prod ./deploy.sh

or

export MY_ENV=prod
./deploy.sh

If your script sets variables meant to persist after execution (modifying $PATH, e.g.), use:

source script.sh
# or shorthand:
. script.sh

Caveat: Sourcing scripts with side effects (like exit or set -e) can litter your interactive shell with unwanted state. Test carefully.


Table: Shell Script Execution Reference

OperationCommandNotes
View script contentscat script.shOr less, nano, vim
Check/modify permissionsls -l script.sh / chmod +x script.sh
Run explicitly with Bashbash script.shIgnores executable bit
Run as standalone script./script.shRequires shebang + executable bit
Pass arguments./script.sh arg1 arg2Accessible via $1, $2, …
Debug line-by-linebash -x script.sh / set -xset -e; trap for error tracing
Syntax only (no run)bash -n script.shUseful for CI pre-checks
Source into current shellsource script.sh or . script.shShares exported variables/functions

Not Quite Obvious: Executing on Non-GNU Systems

Scripts that assume GNU utilities (sed, grep, etc.) may fail on BSD/macOS due to option differences. Explicitly specify versions where possible (e.g., /usr/bin/gsed vs /bin/sed). Check the target shell’s --version for feature set; Bash 4+ features fail on distros with system Bash <4 (many RHEL/CentOS 7 boxes).


Engineering Summary

Running .sh files correctly in Linux is rarely a case of “just run this command.” Secure, predictable automation requires scrutinizing permissions, understanding interpreter paths, being mindful of environment scope, and adopting strong debugging habits.

Trade-off: Strict permissioning and per-shell shebangs increase reliability but add friction to cross-system portability. Harden scripts where safety matters, but remain pragmatic for local tooling.

Write, review, and run scripts as if your infrastructure depends on it—because, eventually, it will.