shell script run when I am root but I get a permission denied when it is invoked from a Makefile (still as root) - linux

I need to run a Make script that invokes a shell script.
I can run the shell script directly as root but when running make on the makefile (still as root) make is denied permission to run the same shell script?
The offending line in the Makefile is that one:
PLATFORM=$(shell $(ROOT)/systype.sh)
I could go in and hardcode the value of every PLATFORM variable of every Makefile scrip on the system but that would be pointless fix, I'd like to understand why there is that Permission Denied error:
make[1]: execvp: ../systype.sh: Permission denied
PS: The content of the shell script is not the issue even if the shell script only contain ls or echo linux the Permission is Denied to the Make utility to run the shell script.
PS: I am not a make expert by an mean so if the explanation is related to Make please be as specific as you can.

In your comments above you say when you "run it manually" you use . scriptname.sh, is that correct? You use . followed by scriptname.sh?
That does not run the script, that sources the script. Your statement that scriptname.sh will execute with and without the x permission since it is a shell script is wrong. You can source the script if you have read permissions. But you cannot execute the script unless you have execute permissions.
"Sourcing" means that a new shell is not started: instead your current shell (where you type that command) reads the contents of the script and runs them just as if you'd typed them in by hand, in the current shell. At the end all the side-effects (directory changes, variable assignments, etc.) that were performed in that script are still available in your current script.
"Executing" means that the script is treated like a program, but the program is a new shell that's started, which then reads the contents of the script and executes it. Once the script ends the shell exits and all side-effects are lost.
The $(shell ...) function in make will not source your script (unless you also use . there, which you did not). It will try to run your script. The error you show implies that either systype.sh did not have the execution bit set, or else that it had an invalid #! line. There's no other explanation I can think of.
If sourcing the file really does what you want then why not just use the same method in $(shell ...) that you use in your own personal use:
PLATFORM=$(shell . $(ROOT)/systype.sh)
If changing the user permission didn't work, are you sure that whatever user owns the script is the same user you're using to invoke make? You say you're "running as root"; is the script owned by root? Or is it owned by you and you're running sudo make or similar?
I don't know why you don't just use:
chmod +x systype.sh
and call it a day.

Adding execution permission to the file Group rather that the file User fixed the issue.
PS: I wonder why? It seems the Make utility run shell scripts not with the same user that started Make...

Related

About script execution permissions on Linux shell

I've just created a script, let's say, "helloworld.sh".
The script doesn't yet have execution permissons: -rw-rw-r--
If I try to execute that script with: "./helloword.sh", I'll get an error message, as expected. But, if I try to execute that same script as: . helloword, it will execute with no problems.
How? Why does that happen?
This happens because on Linux the "." (dot) alone is a built-in command that execute the script within your current session with your current shell. This is the same as calling the script with source command (the BSD default method). It's almost the same than execute with bash helloworld.sh.
When you call the script with ./helloworld.sh or /root/helloworld.sh the shell will try to figure out how to execute it, if the file is a binary, it will simply run, if it is a script, the shell will read the first line looking for the interpreter. To do this, you'll need execution permission.
To simplify:
One is a command;
The other one is a path.
You can even run:
. --help
About . against bash:
This is why we use . or source to load variables from a file in our session, for example, when we change ~/.bashrc and reload it without login again.
You can see this happens when you execute:
. /etc/os-release
All variables defined inside this file will be loaded and available in your current shell session.
The same will not happen if you execute:
bash /etc/os-release
Because you opened a "new session" inside that bash that you called, the new bash executes and close, cleaning the session.
The same process happen if you give execute permission +x to the script, because when you call the script with ./ or something like that, a new session will be created too.

linux file access read/write by root, execute by all

I'm trying to create a shell script that can only be read/written by root but can be executed by everyone. I created a file test.sh, set ownership to "chown root:me test.sh" and set permissions to "chmod 711 test.sh", hoping this would do the trick. However, this results in a file that always needs sudo in order to execute. Is it possible to edit the rights such that anyone (without using sudo) can execute the script, but only root (using sudo) can read/write the file?
this is not possible to be achieved, at least with shell scripts.
In fact, at the moment of the execution, the shell program (I presume Bash) needs to read the content of the shell file and the process runs with your user name and permissions.
Having said this, the BASH program (ZSH, SH or any other shell follow the same rules) needs to be able to read the content of the file and this can be achieved only by granting read privileges +r. So, the bare minimum would be a 755 permission model.
An alternative is to run an actual program which does the job and wouldn't require read permission in order to be executed. But this is a totally different pattern.
This response explains it as well.
https://unix.stackexchange.com/questions/34202/can-a-script-be-executable-but-not-readable

Why do we need execution permission although we can run any script without it using "bash script file"?

I am wondering when and why do we need execution permission in linux although we can run any script without execute permission when we execute that script using the syntax bellow?
bash SomeScriptFile
Not all programs are scripts — bash for example isn't. So you need execute permission for executable programs.
Also, when you say bash SomeScriptFile, the script has to be in the current directory. If you have the script executable and in a directory on your PATH (e.g. $HOME/bin), then you can run the script without the unnecessary circumlocution of bash $HOME/bin/SomeScriptFile (or bash ~/bin/SomeScriptFile); you can simply run SomeScriptFile. This economy is worth having.
Execute permission on a directory is somewhat different, of course, but also important. It permits the 'class of user' (owner, group, others) to access files in the directory, subject to per-file permissions also allowing that.
Executing the script by invoking it directly and running the script through bash are two very different things.
When you run bash ~/bin/SomeScriptFile you are really just executing bash -- a command interpreter. bash in turns load the scripts and runs it.
When you run ~/bin/SomeSCriptFile directly, the system is able to tell this file is a script file and finds the interpreter to run it. There is a big of magic invoking the #! on the first line to look for the right interpreter.
The reason we run scripts directly is that the user (and system) couldn't know or care of the command we are running is a script or a compiled executable.
For instance, if I write a nifty shell script called fixAllIlls and later I decide to re-write it in C, as long a I keep the same interface, the users don't have to do anything different.
To them, it is just a program to run.
edit
The operating system checks permissions first for several reasons:
Checking permissions is faster
In the days of old, you could have SUID scripts, so one needed to check the permission bits.
As a result, it was possible to run scripts that you could not actually read the contents of. (That is still true of binaries.)

I'm learning about shebangs. How do I make it work with node.js in a Mac terminal?

I have:
#!/usr/bin/env node
console.log("It works!");
I learned that env finds the node program and interprets it with node. I checked that env exists in /usr/bin.
When I call node itworks.js it works and outputs It works!. However, from what I understand, I should just be able to call itworks.js without node due to the shebang. But when I make this command it says -bash: itworks.js: command not found.
Could someone help me get the shebang to work?
First of all you need to make the file executable:
chmod +x itworks.js
Then you need to call it by specifying the path as well. Either:
/where/it/is/on/disk/itworks.js
or:
./itworks.js
The reason for :
-bash: itworks.js: command not found
is because bash looks for programs in directories in the PATH environment variable when you do not say where the file is - it does not look in the current directory unless you tell it.
You could update the PATH variable with the current directory shortcut ., but that can be a security risk, so most run the program like this:
./itworks.js
Of course if you put your scripts all in one directory then you could add that to PATH in one of your start-up files. For example, if you had a directory called bin in your home directory that held your scripts:
PATH=$PATH:"$HOME/bin"
You also need to add the execute permissions to the script:
chmod u+x itworks.js
The u indicates that we only give permission for the current user to execute this file. If we omit the u then anyone can run it.

Why calling a script by "scriptName" doesn't work?

I have a simple script cmakeclean to clean cmake temp files:
#!/bin/bash -f
rm CMakeCache.txt
rm *.cmake
which I call like
$ cmakeclean
And it does remove CMakeCache.txt, but it doesn't remove cmake_install.cmake:
rm: *.cmake: No such file or directory
When I run it like:
$ . cmakeclean
it does remove both.
What is the difference and can I make this script work like an usual linux command (without . in front)?
P.S.
I am sure the both times is same script is executed. To check this I added echo meme in the script and rerun it in both ways.
Remove the -f from your #!/bin/bash -f line.
-f prevents pathname expansion, which means that *.cmake will not match anything. When you run your script as a script, it interprets the shebang line, and in effect runs /bin/bash -f scriptname. When you run it as . scriptname, the shebang is just seen as a comment line and ignored, so the fact that you do not have -f set in your current environment allows it to work as expected.
. script is short for source script which means the current shell executes the commands in the script. If there's an exit in there, the current shell will exit (and e. g. the terminal window will close).
This is typically used to modify the environment of the current shell (set variables etc.).
script asks the shell to fork itself, then exec the given script in the child process, and then wait in the father for the termination of the child. If there's an exit in the script, this will be executed by the child shell and thus only terminate this. The father shell stays intact and unaltered by this call.
This is typically used to start other programs from the current shell.
Is this about ClearCase? What did you do in your poor life where you've been assigned to work in the deepest bowels of hell?
For years, I was a senior ClearCase Administer. I haven't touched it in over a decade. My life is way better now. The sky is bluer, bird songs are more melodious, and my dread over coming to work every day is now a bit less.
Getting back to your issue: It's hard to say exactly what's going on. ClearCase does some wacky things. In a dynamic view, the ClearCase repository on Unix systems is hidden in the shell's environment. Now you see it, now you don't.
When you run a shell script, it starts up a new environment. If a particular shell variable is not imported, it is invisible that shell script. When you merely run cmakeclean from the command line, you are spawning a new shell -- one that does not contain your ClearCase environment.
When you run a shell script with a dot prefix like . cmakeclean, you are running that shell script in the current shell which contains your ClearCase environment. Thus, it can see your ClearCase view.
If you're using a snapshot view, it is possible that you have a $HOME/.bashrc that's changing directories on you. When a new shell environment runs in BASH (the default shell in MacOS X and Linux), it first runs $HOME/.bashrc. If this sets a particular directory, then you end up in that directory and not in the directory where you ran your shell script. I use to see this when I too was involved in ClearCase hell. People setup their .kshrc script (it was the days before BASH and most people used Kornshell) to setup their views. Unfortunately, this made running any other shell script almost impossible to do.

Resources