Bash scripting

im making a bash script to automate my shutdown process
its /bin/shutty
the script is
#! /bin/bash
apt update && apt upgrade -t && apt autoremove -y && poweroff

the command works if i type
sudo bash shutty

is there a way to just type sudo shutty or do I need to specify bash
also I thought that putting a # at the beginning of a line would make bash ignore that line

Did you make it executable? (chmod +x /bin/shutty)
#! is an exception to the rule # means ignore

You might like to look at this site - they have a pretty good tutorial on shell scripting that is useful just to know as well as training in the use of:

https://linuxconfig.org/linux-tutorials

You also would need to make an alias if you didn’t want to do ./~/shutty.sh.

no need to make it an alias because its in the /bin folder which means its a system wide binary which can be run from any folder

1 Like

yes I made it executable if i didnt i dont think it would have run at all

If you invoke it with bash, it doesn’t need to be executable so it would have run if you hadn’t

2 Likes

tl;dr: invoking the script as an executable is just a shortcut for calling the script’s interpreter as an executable with the source as an argument, and the execute permissions are only required to get the OS to read the shebang to identify the interpreter, not to get the interpreter to interpret the source file

When you invoke a script by calling the interpreter explicitly, you’re not running the script as an executable per se.

In other words, when you invoke

/bin/bash script.bash

at the command-line, the executable you’re invoking is /bin/bash, and script.bash is merely an argument telling it what source file to read. In this case, not only do you not need script.bash to be marked executable, script.bash does not need a shebang (the #!/bin/bash or, more portably, #/usr/bin/env bash line), either.

When you invoke the script by typing its full path as a command, however, you’re treating the script as an executable†. When the operating system sees a file marked executable which is not a binary executable, it checks to see whether it has a #!<...> line. If it does, it then invokes the interpreter named in the shebang line just like we did manually above. So

/usr/local/bin/script.bash

is transformed into

/usr/bin/env bash /usr/local/bin/script.bash

or whatever, according to your shebang line. But all of this only happens if the shebang is present and the file is marked executable.

—————
†: Generally, ‘executable’ means a binary executable compiled for a given platform. On some Unices (e.g., macOS), shells will read shebang lines of scripts invoked at them and launch them according to the shebang line. On Linux, there’s a kernel feature that interprets shebangs, rendering scripts with shebang lines and the appropriate scripts ‘executables’ in a deeper sense.

5 Likes

ok so strange thing
i removed the line #! /bin/bash
and now it works just by running the command
why didnt anyone know this answer?

Reading the previous post, i believe he DID say that. Just in a longer, more explained way. Or I could be wrong.

1 Like

I haven’t come across something like that, and when you first asked, I recreated your file exactly and ran it on mine and it worked straight off the bat so I can only assume typos? Anyway, I thought it was apt to leave you to solve this yourself after we had explained what’s what.

o.0 I think the reason why “#! /bin/bash” didn’t work is because you have a space between the ! and /. IIRC, it should be “#!/bin/bash”

4 Likes

Yes, I checked my other bash script for installing my favorite programs, and that’s exactly how it is in my script.

I even double checked it just now. That is probably why your script isn’t working correctly.