0

I have a volume attached in kubernetes with path /var/www/aaa/tmp.

That volume was created using path.mkdir() and currently have 755 permissions. It was created with code path.mkdir(parents=True, exist_ok=True) initially.

I'm trying to update its permissions without deleting the existing path.

I'm using path.mkdir(parents=True, exist_ok=True, mode=0o777). I'm still facing issues related to permissions and getting 502 Bad gateway for the flask app that is creating the above directories.

Does the path.mkdir(parents=True, exist_ok=True, mode=0o777) updates the path permissions if it already exists and have 755 permissions? Or will it ignore it completely as we've mentioned exists_ok=True ? I don't see the permissions getting updated for the path.

Should I be deleting the path completely and re-running the path.mkdir..... with mode=0o777 which creates new directories and set permissions?

Edit 1: I've tried using os.chmod() on the path. But it's throwing PermissionError.

Here's the code snippet.

path.mkdir(parents=True, exist_ok=True)
os.chmod(path, mode=0o777)

Error:

File "./app/init.py", line 79, in create_prediction_app create_directories(app) File "./app/init.py", line 36, in create_directories os.chmod(path, mode=0o777) PermissionError: [Errno 1] Operation not permitted: '/var/www/aaa/tmp' unable to load app 0 (mountpoint='') (callable not found or import error) * no app loaded. GAME OVER *

Underoos
  • 4,708
  • 8
  • 42
  • 85

2 Answers2

2

If the path is already existing, you should use the os.chmod(path, mode) instead of deleting/re-creating.

For example:

import os

os.chmod("/var/www/aaa/tmp", 0o777)

Furthermore, the chmod can get the permission from stat module.

  • stat.S_ISUID − Set user ID on execution.
  • stat.S_ISGID − Set group ID on execution.
  • stat.S_ENFMT − Record locking enforced.
  • stat.S_ISVTX − Save text image after execution.
  • stat.S_IREAD − Read by owner.
  • stat.S_IWRITE − Write by owner.
  • stat.S_IEXEC − Execute by owner.
  • stat.S_IRWXU − Read, write, and execute by owner.
  • stat.S_IRUSR − Read by owner.
  • stat.S_IWUSR − Write by owner.
  • stat.S_IXUSR − Execute by owner.
  • stat.S_IRWXG − Read, write, and execute by group.
  • stat.S_IRGRP − Read by group.
  • stat.S_IWGRP − Write by group.
  • stat.S_IXGRP − Execute by group.
  • stat.S_IRWXO − Read, write, and execute by others.
  • stat.S_IROTH − Read by others.
  • stat.S_IWOTH − Write by others.
  • stat.S_IXOTH − Execute by others.

For example:

import os
import stat

# Set a file write by others.
os.chmod("/var/www/aaa/tmp", stat.S_IWOTH)

You can set more permission with the bitwise operator.

For example:

import os
import stat

os.chmod(
    '/var/www/aaa/tmp',
    stat.S_IRUSR |
    stat.S_IROTH |
    stat.S_IRGRP 
)

Complete testing:

>>> touch test_perm.sh
>>> ll test_perm.sh
-rw-rw-r-- test_perm.sh
>>> python -c "import os; os.chmod('test_perm.sh', 0755)"
>>> ll test_perm.sh
-rwxr-xr-x test_perm.sh

EDIT:

If you get PermissionError: [Errno 1] Operation not permitted:... exception when you want to change the permission with os.chmod, you should try the following code part to solve it. It's important to run the script with admin rights (with sudo in Linux environment).

Code:

from getpwnam import pwd
from getgrnam import grp
import os

uid = getpwnam("USERNAME")[2]
gid = grp.getgrnam("GROUPNAME")[2]
os.chown("/var/www/aaa/tmp", uid, gid)

Based on the official chown documentation:

os.chown(path, uid, gid, *, dir_fd=None, follow_symlinks=True)

Change the owner and group id of path to the numeric uid and gid. To leave one of the ids unchanged, set it to -1.

This function can support specifying a file descriptor, paths relative to directory descriptors and not following symlinks.

See shutil.chown() for a higher-level function that accepts names in addition to numeric ids.

Availability: Unix.

New in version 3.3: Added support for specifying path as an open file descriptor, and the dir_fd and follow_symlinks arguments.

Changed in version 3.6: Supports a path-like object.

Link to documentation: https://docs.python.org/3/library/os.html#os.chown

Community
  • 1
  • 1
milanbalazs
  • 4,811
  • 4
  • 23
  • 45
  • There's a mistake in your first snippet. It should be `0o777` instead. Also, `0755` won't work in python3 anymore. `0o` is required. – viraptor Feb 03 '20 at 08:49
  • For some reason it's granting `755` permissions even though I mentioned `mode=0o777` – Underoos Feb 03 '20 at 09:16
  • I have edited my answer based on your PS. I have mentioned a possible solution to solve the `PermissionError: [Errno 1] Operation not permitted:...` exception. – milanbalazs Feb 04 '20 at 12:11
0

milanbalazs' answer is very nice, good explanation, but will only chmod the last directory in the path. In my case this was not good enough, because I needed to ensure every subfolder all the way down the last one was also chmodded.

I couldn't find any simple way to do this with existing bash tools, the only one close to what I needed with was chmod -R but I also didn't want to interfere without anything other than specifically each folder specified in the path.

To clarify, in the example, we have the path /var/www/aaa/tmp. I might want to start from /var/www and ensure that both /var/www/aaa and /var/www/aaa/tmp have their permissions set to whatever I want.

So I wrote the following script to solve this use case;

import os
import argparse

def base8(val):
    return int(val, base=8)

def path(val):
    assert os.path.exists(val)
    return val

def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('start_dir', type=path, help='starting point for chmod to check for subdirectories')
    parser.add_argument('end_dir', help='last directory to be chmodded, relative to start_dir')
    parser.add_argument('permission', type=base8, help='permission to set on each directory (must be base 8 format e.g. "0o750")')

    args = parser.parse_args()
    return args

def main():
    args = parse_args()

    directories = os.path.split(args.end_dir)
    current_dir = args.start_dir
    for directory in directories:
        current_dir = os.path.join(current_dir, directory)
        os.chmod(current_dir, args.permission)

if __name__ == '__main__':
    main()

Hopefully someone finds this useful one day :)

Edward Spencer
  • 448
  • 8
  • 10