For your specific script either way will work, except that
./script.sh requires execution and readable bits, while
bash script.sh only requires readable bit.
The reason of the permissions requirement difference lies in how the program that interprets your script is loaded:
./script.sh makes your shell run the file as if it was a regular executable.
The shell forks itself and uses a system call (e.g.
execve) to make the operating system execute the file in the forked process. The operating system will check the file's permissions (hence the execution bit needs to be set) and forward the request to the program loader, which looks at the file and determines how to execute it. In Linux compiled executables start with an ELF magic number, while scripts start with a
#! (hashbang). A hashbang header means that the file is a script and needs to be interpreted by the program that is specified after the hashbang. This allows a script itself to tell the system how to interpret the script.
With your script, the program loader will execute
/bin/bash and pass
./script.sh as the command-line argument.
bash script.sh makes your shell run
bash and pass
script.sh as the command-line argument
So the operating system will load
bash (not even looking at
script.sh, because it's just a command-line argument). The created
bash process will then interpret the
script.sh because it's passed as the command-line argument. Because
script.sh is only read by
bash as a regular file, the execution bit is not required.
I recommend using
./script.sh though, because you might not know which interpreter the script is requiring. So let the program loader determine that for you.