草庐IT

php - 在 CentOS7 上从 PHP 写入文件(通过执行 git 命令)

coder 2024-04-28 原文

我无法在我的 apache 网络服务器目录中写入文件。我正在使用 CentOS 7。我正在尝试使用 exec 从 PHP 文件执行 git 命令:

exec("/usr/local/bin/git -C ../myRepo fetch 2>&1", $output, $exec_return_value);

通过打印输出,我看到错误显示为:

error: cannot open .git/FETCH_HEAD: Permission denied

我发现(在此博客的帮助下:http://jondavidjohn.com/git-pull-from-a-php-script-not-so-simple/)这是“预期的”,因为 Apache 将使用与我通过 ssh 使用的用户不同的用户执行。因此,我需要确保我的权限允许该用户拥有写入权限。

我确定我的 Apache 安装是以名为“apache”的用户身份执行的,方法是在我的 php 文件中打印此输出:

exec("whoami", $debugOutput, $debugRetVal);

我还按照同一链接中的建议设置了 SSH。但不幸的是,我在 PHP 文件中仍然遇到同样的错误:

error: cannot open .git/FETCH_HEAD: Permission denied

真正让我震惊的是,当我从我的 ssh session 中作为 apache 运行时,我没有任何权限问题:

sudo -u apache /usr/local/bin/git -C ../myRepo fetch

从 PHP 执行时,用户“apache”似乎具有不同的权限。有人可以帮我解决这个问题吗?

最佳答案

我看到的用户“apache”在从 PHP 执行与从我的 SSH 执行时似乎具有不同权限的行为是 SELinux 的结果。当 SELinux 处于其“强制”模式(在 CentOS 7 中默认情况下)时,它本质上是在标准 Linux 用户权限之上“分层”访问保护方案。从简单的意义上说,用户“apache”在httpd进程之外执行时实际上确实具有不同的权限。

要获得更详细的信息,apache“服务”的 html 目录具有“httpd_sys_content_t”的 SELinux 上下文类型。所以我的 git repo 继承了相同的上下文。但是 SELinux 安全策略的工作方式是 httpd 仅具有对上下文类型“httpd_sys_content_t”的读取权限。为了让 httpd 具有对文件的写入权限,我需要将上下文更改为“httpd_sys_rw_content_t”。我这样做是使用:

sudo chcon -R -t httpd_sys_rw_content_t ../myRepo

这终于解决了我原来的错误!不幸的是,它出现了一个新错误,该问题的链接也提到了:

array(5) { [0]=> string(68) "ssh: connect to host PRIVATEGITHOST: Permission denied" [1]=> string(45) "fatal: Could not read from remote repository." [2]=> string(0) "" [3]=> string(51) "Please make sure you have the correct access rights" [4]=> string(26) "and the repository exists." } 

但正如我在问题中提到的,我已经按照博客的建议为“apache”用户设置了一个 ssh key 。所以这实际上是一个不同的错误。再次出现源自 SELinux 的错误。

默认情况下,有一个名为“httdp_can_network_connect”的 SELinux bool 值被设置为关闭。这可以防止 httpd 建立自己的外部连接。如果您所做的只是提供服务器上存在的内容,那么这就是您想要的。出于我的目的,我需要将该 bool 值设置为 on using:

sudo setsebool httpd_can_network_connect on

在拔掉我的头发 2 天之后。我最终可以从 php 文件中执行“git fetch”。

我使用“audit2allow”工具​​调试了 bool 值的最终错误,该工具查看一些 SELinux 日志并以或多或少的简单英语告诉您如何解决问题。

sudo audit2allow -a

OUTPUT:
#============= httpd_t ==============
#!!!! This avc can be allowed using one of the these booleans:
#     nis_enabled, httpd_can_network_connect
allow httpd_t unreserved_port_t:tcp_socket name_connect;

如果有人遇到与 apache/httpd 相关的 SELinux 问题,我强烈建议您查看该工具。

为了完整起见,我想指出像我上面所做的那样更改我的存储库的文件上下文是一个“临时更改”并且不会通过系统重置持续存在。为了永久更改我使用的上下文类型:

sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/myRepo(/.*)?"

同样,我用它来永久更改 bool 值:

sudo setsebool -P httpd_can_network_connect on

关于php - 在 CentOS7 上从 PHP 写入文件(通过执行 git 命令),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41604203/

有关php - 在 CentOS7 上从 PHP 写入文件(通过执行 git 命令)的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  3. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  4. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  5. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  6. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  7. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  8. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  9. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  10. ruby-on-rails - 无法在centos上安装therubyracer(V8和GCC出错) - 2

    我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e

随机推荐