Your first bash script
Create an executable script that prints hi.
Why
A deploy script, a backup script, a log-rotation script: they're all built the same way. It's a text file with commands you'd otherwise have to type by hand. For the system to run such a file as a program, it needs two things. The first line says which interpreter reads it. And the file needs the execute bit set.
If either is missing, the script won't start. The errors are short and
confusing: Permission denied, command not found,
cannot execute: required file not found. This lesson covers where each
one comes from.
Concepts
A script is a plain text file with shell commands, one per line. The shell runs them top to bottom, as if you typed them in one after another.
A shebang is the first line of a script, starting with #!. After #!
comes the full path to the interpreter: #!/bin/sh or #!/bin/bash. When
you run the script as a program, the kernel reads this line and hands the
file to that interpreter.
The execute bit (x in the permissions) lets you run a file as a
program. A new file doesn't get it: with the usual 022 mask it's created
with rw-r--r-- permissions. chmod +x sets the bit.
PATH is a variable holding a list of folders where the shell looks for
a command whose name has no / in it. The current folder isn't on that
list.
How it works
Writing the file
There's no text editor in the lab, so it's easiest to create the file from
the command line. The construct cat > file <<'EOF' writes everything you
type, up to the line EOF, into the file:
cat > /root/greet.sh <<'EOF'
#!/bin/sh
echo hello
EOF
The quotes around 'EOF' stop the shell from expanding variables inside
the text: exactly what you typed lands in the file. A short script can also
go in one command, where \n means a line break:
printf '#!/bin/sh\necho hello\n' > /root/greet.sh
Check what you got:
cat /root/greet.sh
#!/bin/sh
echo hello
#!/bin/sh or #!/bin/bash
/bin/sh is the POSIX shell. On Ubuntu and Debian it's a link to dash, a
small, fast shell. On Alpine it's busybox sh. For simple scripts with
echo, variables, if, and loops, it's enough.
#!/bin/bash is for when you need bash-specific features: arrays,
[[ ... ]], $'...'. Minimal images like Alpine don't have bash by
default, and such a script won't run there.
ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Mar 31 2024 /bin/sh -> dash
On another system the link may point somewhere else.
The execute bit
A file you just created can't be run as a program yet:
ls -l /root/greet.sh
-rw-r--r-- 1 root root 21 Oct 10 10:00 /root/greet.sh
/root/greet.sh
bash: /root/greet.sh: Permission denied
chmod +x adds x for the owner, the group, and everyone else (subject to
umask); chmod u+x adds it only for the owner:
chmod +x /root/greet.sh
ls -l /root/greet.sh
-rwxr-xr-x 1 root root 21 Oct 10 10:00 /root/greet.sh
Permissions and the numeric notation are covered in the "Permissions" lesson.
Three ways to run it
./greet.shruns the file from the current folder. The dot means the current folder, and/tells the shell this is a path, not a command name./root/greet.shdoes the same by full path, and works from any folder.sh greet.shorbash greet.shrun the interpreter directly and pass it the file. The execute bit isn't needed here, and the shebang isn't used.
Just greet.sh without a path won't work, even if you're in the same
folder:
greet.sh
bash: greet.sh: command not found
The shell only looks for a command without / in the folders listed in
PATH, and the current folder isn't one of them. To run a script by name,
put it in one of those folders, for example /usr/local/bin.
What the shebang does
If you run the file as a program (./greet.sh), the kernel looks at the
first two bytes. It sees #!, takes the path from the first line, and runs
/bin/sh /root/greet.sh. So the path has to be exact: a typo like
#!/bin/shh means the kernel can't find the interpreter.
bash: ./greet.sh: cannot execute: required file not found
That's what bash prints. Run it from sh (dash) and the text differs:
./greet.sh: not found. The meaning is the same either
way: the script file exists, but there's no interpreter at the path from
the shebang.
Without a shebang, the behavior depends on who runs it. Bash and dash will
run such a file as a script on their own, but a program that calls it
directly (for example, docker exec or systemd) gets an
exec format error. That's why you always write a shebang.
Common mistakes
- Forgot
chmod +x../script.shfails withPermission denied, even thoughsh script.shworks. - Run by name without
./.command not found, even though the file is right there. - Shebang not on the first line. A blank line or a space before
#!, and it's no longer a shebang, just a comment. - File saved with Windows line endings. Windows editors put two
characters at the end of a line,
\r\n, while Linux expects just\n. The extra\rsticks to the path from the shebang, giving/bin/sh\r, which doesn't exist.cat -Ashows the invisible characters:\rlooks like^Mbefore$. Remove them withsed -i 's/\r$//' fileortr -d '\r' < file > new_file. #!/bin/bashin an image without bash. On Alpine, such a script fails withsh: /b.sh: not found, even though the file is right there: bash just isn't found. Write#!/bin/shor install bash.
What you'll need for the tasks
- Enter a container with
docker exec -it <name> bashand exit withexit. - Create a file with
cat > file <<'EOF'orprintf, check it withcatandcat -A. - Permissions:
ls -l,chmod +x. - Running it:
./file, a full path,sh file. - Lab 2 needs the "What the shebang does" and "Common mistakes" sections.
Practice in your browser
Linux runs right here. Solve the task and we'll save your progress automatically.
Script /root/hello.sh
Create the file /root/hello.sh so that running it prints the line hi. Make the file executable (chmod +x) so you can run ./hello.sh.
0%
Go through it with an AI agent
The agent explains anything unclear in plain words, gives you 2 labs for this lesson and drills you on interview questions. $49 one-time, lifetime access.
Tell the agent: use MCP izi, give me lesson terminal-scripts-01-hello-script
Progress saved in this browser
Clear your history or open this on your phone, and the marks will be gone. Leave your email and they'll move to your account. No password needed.
Done. moved to your account. You can see your progress on any device. My progress