Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a file with python using sudo makes its owner root

i have a simple piece of python script called myCreate.py running on linux:
fo = open("./testFile.txt", "wb")

when i run python ./myCreate.py - the owner of testFile.txt stays my user. when i run sudo python ./myCreate.py - the owner of testFile.txt is now root.

testFile.txt was not run previously to both of the executions

how can i make the owner of the file stay the real user and not the effective user?! Thanks!

like image 867
iddqd Avatar asked Sep 11 '14 15:09

iddqd


3 Answers

Running your script with sudo means you run it as root. So it's normal your file is owned by root.

What you could do is to change the ownership of the file after it is created. In order to do this, you need to know which user runs sudo. Fortunately, there is a SUDO_UID environment variable that is set when you use sudo.

So, you can do:

import os
print(os.environ.get('SUDO_UID'))

Then, you need to change the file ownership:

os.chown("path/to/file", uid, gid)

If we put it together:

import os

uid = int(os.environ.get('SUDO_UID'))
gid = int(os.environ.get('SUDO_GID'))

os.chown("path/to/file", uid, gid)

Of course, you'll want it as a function, because it's more convenient, so:

import os

def fix_ownership(path):
    """Change the owner of the file to SUDO_UID"""

    uid = os.environ.get('SUDO_UID')
    gid = os.environ.get('SUDO_GID')
    if uid is not None:
        os.chown(path, int(uid), int(gid))

def get_file(path, mode="a+"):
    """Create a file if it does not exists, fix ownership and return it open"""

    # first, create the file and close it immediatly
    open(path, 'a').close()

    # then fix the ownership
    fix_ownership(path)

    # open the file and return it
    return open(path, mode)

Usage:

# If you just want to fix the ownership of a file without opening it
fix_ownership("myfile.txt")

# if you want to create a file with the correct rights
myfile = get_file(path)

EDIT: Updated my answer thanks to @Basilevs, @Robᵩ and @5gon12eder

like image 173
Agate Avatar answered Oct 16 '22 09:10

Agate


Use os.chown(), using os.environ to find the appropriate user id:

import os

fo = open("./testFile.txt", "wb")
fo.close()
os.chown('./testFile.txt',
         int(os.environ['SUDO_UID']),
         int(os.environ['SUDO_GID']))
like image 2
Robᵩ Avatar answered Oct 16 '22 09:10

Robᵩ


How about using os.stat to first get the permissions of the containing folder and then applying them to the file post creation.

this would look something like (using python2):

import os

path = os.getcwd()
statinfo = os.stat(path)

fo = open("./testFile.txt", "wb")
fo.close()
euid = os.geteuid()
if (euid == 0) # Check if ran as root, and set appropriate permissioning afterwards to avoid root ownership
    os.chown('./testFile.txt', statinfo.st_uid, statinfo.st_gid)

As Elliot pointed out, if you were to be creating several files simultaneously, this would be better structured as a function.

like image 2
cbrendanprice Avatar answered Oct 16 '22 10:10

cbrendanprice