Установить бит выполнения для файла с помощью python

Используя python в Mac OS, я хотел бы открыть файл для записи и поместить в него некоторые команды оболочки. Позже будет работать в терминале.

with open("my_script.sh", "w") as fd:
    fd.write("#!/bin/sh\n")
    fd.write("echo $PATH\n")

Это создаст файл, но я не мог понять, как установить бит выполнения, поэтому, когда я запускаю его в терминале, я не получу:

sh: my_script.sh: Permission denied

Ответ 1

import os
os.chmod("my_script.sh", 0744)

Правильно выберите значение. Некоторые значения могут быть небезопасными.

Ответ 2

Вы всегда можете сделать это из оболочки терминала, прежде чем запускать его, используя chmod:

chmod a+x my_script.sh

Если вы хотите сделать это с Python, вы можете использовать chmod или fchmod в модуле os. Поскольку у вас уже открыт файл, я бы сделал последнее:

with open("my_script.sh", "w") as fd:
    fd.write("#!/bin/sh\n")
    fd.write("echo $PATH\n")
    os.fchmod(fd.fileno(), stat.S_IRWXU | stat.S_IRWXG | stat.S_IROTH | stat.S_IXOTH)

К сожалению, как вы можете видеть, нет прямого эквивалента chmod a+x добавления флага x для всех, оставив все остальное в одиночестве. Но вы можете сделать то же самое, что и инструмент командной строки chmod на самом деле: stat файл (или, в этом случае, fstat), чтобы получить существующие разрешения, а затем измените их:

with open("my_script.sh", "w") as fd:
    fd.write("#!/bin/sh\n")
    fd.write("echo $PATH\n")
    mode = os.fstat(fd.fileno()).st_mode
    mode |= stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
    os.fchmod(fd.fileno(), stat.S_IMODE(mode))

(На самом деле вам не нужен шаг S_IMODE на большинстве платформ, потому что либо st_mode не имеет никаких дополнительных битов, либо (f) chmod безвредно игнорирует их, как это делает OS X. Но это лучше делать правильные вещи, чтобы сделать ваш код переносимым и будущим.)

Большинство людей считают "дружественные" имена, такие как S_IXUSR, не особенно дружелюбными, и как только вы научитесь думать о режимах в восьмеричных терминах, это проще, чем пытаться вспомнить, как POSIX аббревиатизирует вещи, поэтому вы можете предпочесть это:/p >

with open("my_script.sh", "w") as fd:
    fd.write("#!/bin/sh\n")
    fd.write("echo $PATH\n")
    mode = os.fstat(fd.fileno()).st_mode
    mode |= 0o111
    os.fchmod(fd.fileno(), mode & 0o7777)

111 означает исполняемый файл пользователем, группой и т.д. (то же самое, что и | для различных бит ST_IX*), а 7777 - все биты, которым вы можете перейти (f ) chmod (то же самое, что и S_IMODE).