在 setup.py 文件中设置文件权限

发布于 2024-11-05 17:04:54 字数 293 浏览 5 评论 0原文

我使用 setup.py 创建了一个 python 软件安装。在此软件中,当我使用 setup.py 安装这些 xml 文件时,我使用数据文件(XML 文件),然后这些文件与其他文件一起保存在 /usr/lib/python2.7/site_packages/XYZ 中。但是为这些文件(XML 文件)设置的文件权限 rwx----- 意味着只有超级用户(root)可以读取这些文件我想将 XML 文件的文件权限更改为 rwxr----- 表示当前用户也可以读取该文件。如何更改数据文件权限。

I created a python software install with setup.py . In this software I use data files (XML file) when I install these xml file using setup.py then these files save with other files in /usr/lib/python2.7/site_packages/XYZ . But file permission set to these files (XML Files) rwx------ means only super user(root) can read these file I want to change the file permission of XML files as rwxr----- means current user can also read that file. How do I change the data files permission.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

大海や 2024-11-12 17:04:54

正确的方法是覆盖 install 命令,以下是具体操作方法。

首先在 setup.py 的开头添加以下导入:

from setuptools.command.install import install
from distutils import log # needed for outputting information messages 

然后您需要创建一个可调用的命令类,下面是一个示例,我创建一个命令类来安装脚本并确保它是只能对 root 执行(Python 中还有其他方法。例如,如果你的 UID 不为 0,你可以随时退出脚本。)
我还在这里使用另一个导入:

from setuptools.command.install_scripts import install_scripts

class OverrideInstall(install):

    def run(self):
        uid, gid = 0, 0
        mode = 0700
        install.run(self) # calling install.run(self) insures that everything that happened previously still happens, so the installation does not break! 
        # here we start with doing our overriding and private magic ..
        for filepath in self.get_outputs():
            if self.install_scripts in filepath:
                log.info("Overriding setuptools mode of scripts ...")
                log.info("Changing ownership of %s to uid:%s gid %s" %
                         (filepath, uid, gid))
                os.chown(filepath, uid, gid)
                log.info("Changing permissions of %s to %s" %
                         (filepath, oct(mode)))
                os.chmod(filepath, mode)

现在该类已创建。我通知安装程序,在命令行中看到 install 时应该调用此类:

setup(
      # keep
      # all the previous keywords you had ...
      # add
      cmdclass={'install': OverrideInstall}
      ) 

我希望这个答案有所帮助。

The correct way to do it would be to override the install command, here is how to do it.

First in the beginning of your setup.py add the following imports:

from setuptools.command.install import install
from distutils import log # needed for outputting information messages 

Then you need to create a callable command class, here is an example where I create a command class that installs a script and makes sure that it's only executable for root (The are other ways to that in python. For example you can always exit the script, if you UID is not 0.)
I am also using another import here:

from setuptools.command.install_scripts import install_scripts

class OverrideInstall(install):

    def run(self):
        uid, gid = 0, 0
        mode = 0700
        install.run(self) # calling install.run(self) insures that everything that happened previously still happens, so the installation does not break! 
        # here we start with doing our overriding and private magic ..
        for filepath in self.get_outputs():
            if self.install_scripts in filepath:
                log.info("Overriding setuptools mode of scripts ...")
                log.info("Changing ownership of %s to uid:%s gid %s" %
                         (filepath, uid, gid))
                os.chown(filepath, uid, gid)
                log.info("Changing permissions of %s to %s" %
                         (filepath, oct(mode)))
                os.chmod(filepath, mode)

Now the class is created. I notify the installer that upon seeing install in the command line this class should be invoked:

setup(
      # keep
      # all the previous keywords you had ...
      # add
      cmdclass={'install': OverrideInstall}
      ) 

I hope this answer helps.

情深缘浅 2024-11-12 17:04:54

我使用 setup.py 来构建各种 RPM。解决方案对我来说有点不同。我还认为它更强大有两个原因:

  1. 我可以显式覆盖文件的权限,
  2. 我不需要知道用户的 uid 和 gid。相反,我可以使用纯文本。

这是一个工作示例,

from distutils.core import setup
import distutils.command.bdist_rpm
import distutils.command.install

version='13'

data_files = [
    ('/usr/share/blah', ['README', 'test.sh']),
]

permissions = [
    ('/usr/share/blah', 'test.sh', '(755, sri, sri)'),
]

class bdist_rpm(distutils.command.bdist_rpm.bdist_rpm):

    def _make_spec_file(self):
        spec = distutils.command.bdist_rpm.bdist_rpm._make_spec_file(self)
        for path, files , perm in permissions:

            ##
            # Add a line to the SPEC file to change the permissions of a
            # specific file upon install.
            #
            # example:
            #   %attr(666, root, root) path/file
            #
            spec.extend(['%attr{} {}/{}'.format(perm, path, files)])

        return spec


setup(name='sri-testme',
      version=version,
      description='This is garganbe and is only used to test the permision flag behavior',
      author='Chris Gembarowski',
      author_email='[email protected]',
      url='https://www.python.org/sigs/distutils-sig/',
      data_files=data_files,
      cmdclass={'bdist_rpm':bdist_rpm}
     )

让我更详细地解释一下发生了什么。 RPM 是根据 SPEC 文件构建的。 bdist_rpm 构建一个 SPEC 文件。在 SPEC 文件中,您可以通过提供 %attr 选项来选择文件的权限和所有权。

在使 test.sh 可执行并由用户“sri”拥有的示例中,我将 %attr(755, sri, sri) 添加到 SPEC 文件的末尾。

因此,当我覆盖 bdist_rpm._make_spec_file 的行为时,我所做的就是为我想要覆盖权限的每个文件添加一行。

此示例中的完整 SPEC 文件为:

%define name sri-testme
%define version 13
%define unmangled_version 13
%define release 1

Summary: This is garganbe and is only used to test the permision flag behavior
Name: %{name}
Version: %{version}
Release: %{release}
Source0: %{name}-%{unmangled_version}.tar.gz
License: UNKNOWN
Group: Development/Libraries
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
Prefix: %{_prefix}
BuildArch: noarch
Vendor: Chris Gembarowski <[email protected]>
Url: https://www.python.org/sigs/distutils-sig/

%description
UNKNOWN

%prep
%setup -n %{name}-%{unmangled_version}

%build
python setup.py build

%install
python setup.py install -O1 --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES

%clean
rm -rf $RPM_BUILD_ROOT

%post
##
# sri will be turned on in the run-once script instead of here
#


%preun
#!/bin/bash



%files -f INSTALLED_FILES
%defattr(-,root,root)
%attr(755, sri, sri) /usr/share/blah/test.sh

I use setup.py to build RPMs of all kinds. The solution is a little different for me. I also think that it's more robust for two reasons:

  1. I can override the permissions of a file explicitly
  2. I don't need to know the uid and gid of the user. Instead I can use plain text.

here is a working example

from distutils.core import setup
import distutils.command.bdist_rpm
import distutils.command.install

version='13'

data_files = [
    ('/usr/share/blah', ['README', 'test.sh']),
]

permissions = [
    ('/usr/share/blah', 'test.sh', '(755, sri, sri)'),
]

class bdist_rpm(distutils.command.bdist_rpm.bdist_rpm):

    def _make_spec_file(self):
        spec = distutils.command.bdist_rpm.bdist_rpm._make_spec_file(self)
        for path, files , perm in permissions:

            ##
            # Add a line to the SPEC file to change the permissions of a
            # specific file upon install.
            #
            # example:
            #   %attr(666, root, root) path/file
            #
            spec.extend(['%attr{} {}/{}'.format(perm, path, files)])

        return spec


setup(name='sri-testme',
      version=version,
      description='This is garganbe and is only used to test the permision flag behavior',
      author='Chris Gembarowski',
      author_email='[email protected]',
      url='https://www.python.org/sigs/distutils-sig/',
      data_files=data_files,
      cmdclass={'bdist_rpm':bdist_rpm}
     )

Let me explain what's going on in more detail. RPMs are built from a SPEC file. bdist_rpm builds a SPEC file. In a SPEC file, you can select the permissions and ownership of a file by supplying the %attr option.

In the example to make test.sh executable and owned by user 'sri' I would add %attr(755, sri, sri) to the end of the SPEC file.

So when I override the behavior of bdist_rpm._make_spec_file all I'm doing is adding a line for each file that I want to override the permissions on.

The full SPEC file from this example would be:

%define name sri-testme
%define version 13
%define unmangled_version 13
%define release 1

Summary: This is garganbe and is only used to test the permision flag behavior
Name: %{name}
Version: %{version}
Release: %{release}
Source0: %{name}-%{unmangled_version}.tar.gz
License: UNKNOWN
Group: Development/Libraries
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
Prefix: %{_prefix}
BuildArch: noarch
Vendor: Chris Gembarowski <[email protected]>
Url: https://www.python.org/sigs/distutils-sig/

%description
UNKNOWN

%prep
%setup -n %{name}-%{unmangled_version}

%build
python setup.py build

%install
python setup.py install -O1 --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES

%clean
rm -rf $RPM_BUILD_ROOT

%post
##
# sri will be turned on in the run-once script instead of here
#


%preun
#!/bin/bash



%files -f INSTALLED_FILES
%defattr(-,root,root)
%attr(755, sri, sri) /usr/share/blah/test.sh
凉风有信 2024-11-12 17:04:54

无需编辑 setup.py 的解决方案

如果您只想安装现有软件包而不编辑其 setup.py,请尝试

sudo sh -c 'umask 0; \
    python setup.py install --installed files.txt && \
    xargs chmod -R a+rX < files.txt'

通过编辑 setup.py 解决方案>

如果可以选择编辑 setup.py 文件,则快速而肮脏的修复方法是将其添加到 setup.py 的顶部:

import os, subprocess
# Set a reasonable umask.
os.umask(0o022)
# Make all local files readable and all directories listable.
subprocess.call(['chmod', '-R', 'a+rX', '.'])

这将适用于Linux,但可能不适用于其他操作系统。如果您需要支持其他操作系统,或者只想更改已安装文件的权限,请将 chmod 调用替换为更复杂的内容,例如 这个其他答案

解释

除了复制文件以使 htey 只能由 root 读取之外,我在创建只能由 root 读取的文件夹时遇到了问题。事实证明,setup.py 创建的文件夹的权限是由我的 umask 决定的,并且我相信 setup.py 复制的文件的权限> 被保留,但我对此不太确定。

规范声明 :)

我认为 setup.py install 应该有责任使用合理的默认值 - 例如,当我使用 apt 安装软件时,它会忽略我的 < code>umask 正如它应该的那样。

Solution Without Editing setup.py

If you just want to install an existing package without editing its setup.py, then try

sudo sh -c 'umask 0; \
    python setup.py install --installed files.txt && \
    xargs chmod -R a+rX < files.txt'

Solution By Editing setup.py

If editing the setup.py file is an option, a quick-and-dirty fix is to add this to the top of the setup.py:

import os, subprocess
# Set a reasonable umask.
os.umask(0o022)
# Make all local files readable and all directories listable.
subprocess.call(['chmod', '-R', 'a+rX', '.'])

This will work on Linux, but perhaps not on other OSes. If you need to support other OSes, or only want to change permissions on the installed files, then replace the chmod call with something more sophisticated like in this other answer.

Explanation

I had problems with setup.py install creating folders that were only readable by root, in addition to copying files with so that htey were only readable by root. It turns out the permissions on folders created by setup.py were determined by my umask, and I believe the permissions on files copied by setup.py are preserved, but I'm less sure about this.

Normative Statement :)

I think it should be the responsibility of setup.py install to use sane defaults -- for example, when I use apt to install software it ignores my umask as it should.

翻身的咸鱼 2024-11-12 17:04:54

以 root 身份登录,然后在 shell 中输入:

chmod 744 你的文件名

Login as root, and in the shell type :

chmod 744 yourfilename

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文