-1

I have a brand-new file called ./foo, which looks like this:

#!/usr/bin/env bash

echo 'Hello world'

The output of the umask command looks like so:

$ umask -S
u=rwx,g=rx,o=rx

$ umask
022

Yet, when I try to execute the brand-new file (no chmod yet), I get the following:

$ ./foo

zsh: permission denied: ./foo

For what it's worth, I get the same thing when I open a bash shell:

$ bash

The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.

bash-3.2$ ./foo

bash: ./foo: Permission denied

And when I inspect the file's permissions with ls -l, it also appears to not be executable:

$ ls -l foo

-rw-r--r--  1 richiethomas  staff  40 Mar  3 10:11 foo

When I chmod the file, however, it works as expected:

$ chmod +x foo

$ ./foo
Hello world

$ ls -l foo
-rwxr-xr-x  1 richiethomas  staff  40 Mar  3 10:11 foo

Using this document as a source, I learned that a umask value of 022 means "Owner has all permissions. Everyone else can read and execute, but not write."

If umask is telling me that a file's creator (i.e. me) should be able to execute the file by default, why am I not in fact able to do so?

Richie Thomas
  • 3,073
  • 4
  • 32
  • 55
  • Is this helpful? [what is the difference between umask and chmod](https://superuser.com/questions/1030110/what-is-the-difference-between-umask-and-chmod) – Mattia Righetti Mar 03 '23 at 13:21
  • @MattiaRighetti thanks but that link doesn't appear to address my question, which is about why the permissions returned from `umask` don't appear to reflect my actual permissions, as reflected in my ability to execute a file. – Richie Thomas Mar 03 '23 at 13:29

2 Answers2

2

The only way I know to make a file executable immediately on creation without using hidden steps (like in a function or script) is to create it by copying another file that is already executable. You could use this to make a base template, then edit the file as needed.

$ echo echo hi > a
$ ./a
-bash: ./a: Permission denied
$ chmod +x a
$ ./a
hi
$ cp a b
$ ./b
hi

...but in general, the default behaviors are always there for a reason. Please think about those reasons before changing them. I'm not saying you shouldn't customize your environment however is needed, just that you should be aware of the possible consequences in the specific context. This might save you a bit of time and a few spoons on a dev sandbox, but don't let it go to a company prod system without really thinking it through.

Paul Hodges
  • 13,382
  • 1
  • 17
  • 36
  • It makes sense to leave the defaults as they are unless we have a good reason not to. That said, any idea why the default in this case is that a file's creator can't execute their own file, which they just created? That seems like an unnecessary extra step. – Richie Thomas Mar 03 '23 at 15:48
  • 1
    Because most files are data, and this is *generally* safer in the unknown broader context. The folk designing the system built it to be easy for me to do quick scripting work, especially on a dedicated private machine, but also easy for sysadmins to manage if the machine is a highly networked production system where very few people should be *creating* new scripts. When in doubt, a more conservative decision is safer, and the risk tolerances of end users vary *wildly*. – Paul Hodges Mar 03 '23 at 16:00
  • It sounds like this default is designed to address the case where, for example, a malicious user gains access to a system they shouldn't have access to, and creates a destructive script. In this scenario, with the defaults they way they currently are, that malicious user would be unable to actually execute it without first being given that permission by a sysadmin, which (presumably) that sysadmin wouldn't do. Is that a correct read of the intent here? – Richie Thomas Mar 03 '23 at 17:23
  • It's one possible example. What I don't understand is why it's so important that you be able to create an executable in one action. If it's just the time invested, make a function or script, as mentioned above, that automates the steps into a single command. Let the machine to the tediuos bits. – Paul Hodges Mar 03 '23 at 22:19
  • There's nothing specific I'm trying to accomplish; it's strictly a learning exercise. I'm trying to better understand file and directory permissions as part of leveling up my terminal skills. That includes understanding why the defaults are the way they are. Until I read the answers on this post, it seemed counter-intuitive to me that UNIX would make a file's author jump through `chmod` hoops before allowing them to execute their own file. Now it makes much more sense. – Richie Thomas Mar 03 '23 at 23:25
1

The umask value that you have does reflect the final permissions of your newly created file.

I learned that a umask value of 022 means "Owner has all permissions. Everyone else can read and execute, but not write."

This is incorrect, umask of 022 tells you that newly created files are readable by everyone, but only writable by the owner.

Indeed, default file permission is 666 upon creation and the 022 will set it to 644 which is what you end up with

$ umask
022

$ touch file.txt
$ stat -c "%a" file.txt
644

$ ls -la
.rw-r--r-- someuser file.txt

If you want to make a file executable by default by exploiting umask, then there is no way to achieve that because the default value upon creation is 666, and for a file to be executable by owner, you would need at least 766.

To give it execution rights you have to use chmod as you did in your OP

$ chmod 744 file.txt
$ ls -la
.rwxr--r-- someuser file.txt

There are some good explanations here on how umask works if you want to dig deeper into this.

If you want to create a file and make it executable with a single command, you could create a function like this in ~/.utils.sh

function touch_rwx() {
    touch $1
    chmod 744 $1
}

You could then source the .sh file and this is the outcome

$ touch_rwx file.txt
$ ls -la
.rwxr--r-- file.txt

If you use this frequently, I would suggest to add .utils.sh in your PATH so that you can use it whenever you want in all your newly created shell sessions.

Mattia Righetti
  • 1,265
  • 1
  • 18
  • 31
  • So, I don't necessarily care about exploiting `umask` to make a file executable. My main goal is to create a file that is executable as soon as it's created, without having to run `chmod` on it. One of my mistakes is that I thought `6--` included `execute` permissions for the creator, but now I see that I would need at least `7--` for that. So how do I create a file that ships with `7--` permissions by default? – Richie Thomas Mar 03 '23 at 13:56
  • It's not possible with shell builtins, as far as I know. A possible solution would be to create a bash `function` that is going to create a new file and run `chmod` soon after that. – Mattia Righetti Mar 03 '23 at 13:59