【问题标题】:How to get the home directory from a PHP CLI script?如何从 PHP CLI 脚本获取主目录?
【发布时间】:2009-12-12 22:33:44
【问题描述】:

从命令行,我可以像这样获取主目录:

~/

如何在我的 PHP CLI 脚本中获取主目录?

#!/usr/bin/php
<?php
echo realpath(~/);
?>

【问题讨论】:

    标签: php


    【解决方案1】:

    使用$_SERVER['HOME']


    编辑:

    为了让它完整,看看print_r($_SERVER)给了我什么,从命令行执行:

    Array
    (
        [TERM_PROGRAM] => Apple_Terminal
        [TERM] => xterm-color
        [SHELL] => /bin/bash
        [TMPDIR] => /var/folders/Lb/LbowO2ALEX4JTK2MXxLGd++++TI/-Tmp-/
        [TERM_PROGRAM_VERSION] => 272
        [USER] => felix
        [COMMAND_MODE] => unix2003
        [__CF_USER_TEXT_ENCODING] => 0x1F5:0:0
        [PATH] =>/Library/Frameworks/Python.framework/Versions/Current/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/texbin:/usr/X11/bin
        [PWD] => /Users/felix/Desktop
        [LANG] => de_DE.UTF-8
        [SHLVL] => 1
        [HOME] => /Users/felix
        [LOGNAME] => felix
        [DISPLAY] => /tmp/launch-XIM6c8/:0
        [_] => ./test_php2
        [OLDPWD] => /Users/felix
        [PHP_SELF] => ./test_php2
        [SCRIPT_NAME] => ./test_php2
        [SCRIPT_FILENAME] => ./test_php2
        [PATH_TRANSLATED] => ./test_php2
        [DOCUMENT_ROOT] => 
        [REQUEST_TIME] => 1260658268
        [argv] => Array
          (
            [0] => ./test_php2
          )
    
        [argc] => 1
        )
    

    希望我不要暴露相关的安全信息;)

    Windows 兼容性

    请注意,$_SERVER['HOME'] 在 Windows 上不可用。而是将变量拆分为$_SERVER['HOMEDRIVE']$_SERVER['HOMEPATH']

    【讨论】:

    • +1 令人惊讶的是,有多少人对这个简单的问题给出了同样明显错误的答案。
    • 我没有您发布的关于 Windows 兼容性的任何变量。我转储了所有 SERVER 数组并且无法获取我当前的配置文件,可能是由于启动 wamp 服务器时使用了管理员权限。有什么建议吗?
    • @erm3nda:对不起,我不使用 Windows。 mauris 添加了有关 Windows 兼容性的信息。
    • 最后我使用了一个批处理文件来运行 php 脚本,使用 %PROFILE% 作为位置并将 argv[1] 传递给 php。所以现在我可以将一个 php 文件拖到批处理中,并使用我的桌面作为输出目录运行它。不是很酷,但这是我发现的独特解决方法。谢谢。
    • 如果 $_SERVER$_ENV 不起作用,请尝试 getenv("HOME")
    【解决方案2】:

    您可以从环境中获取 $HOME 的值:

    <?php
        $home = getenv("HOME");
    ?>
    

    【讨论】:

    • 在 Windows 上 getenv 似乎不区分大小写。而在 linux 上,它是区分大小写的。
    • 这会在我的 Mac OS X 10.10 Apache 安装中返回空字符串。
    【解决方案3】:

    这对我适用于 LINUX 和 WINDOWS:

    function get_home_path() {
      $p1 = $_SERVER['HOME'] ?? null;       // linux path
      $p2 = $_SERVER['HOMEDRIVE'] ?? null;  // win disk
      $p3 = $_SERVER['HOMEPATH'] ?? null;   // win path
      return $p1.$p2.$p3;
    }
    

    【讨论】:

      【解决方案4】:

      PHP 允许您获取任何操作系统用户的主目录。有两种方式。

      方法#1:

      首先,您必须找出操作系统用户 ID 并将其存储在某处(例如数据库或配置文件)。

      // Obviously this gotta be ran by the user which the home dir 
      // folder is needed.
      $uid = posix_getuid();
      

      只要您传递之前收集的正确目标用户 ID,任何操作系统用户都可以运行此代码位,甚至是通常的网络服务器 www-data 用户。

      $shell_user = posix_getpwuid($uid);
      print_r($shell_user);  // will show an array and key 'dir' is the home dir
      
      // not owner of running script process but script file owner
      $home_dir = posix_getpwuid(getmyuid())['dir'];
      var_dump($home_dir);
      

      Documentation

      方法#2:

      与 posix_getpwuid() 的逻辑相同。在这里你必须传递目标操作系统用户名而不是他们的 uid。

      $shell_user = posix_getpwnam('johndoe');
      print_r($shell_user); // will show an array and key 'dir' is the home dir
      
      // not owner of running script process but script file owner
      $home_dir = posix_getpwnam(get_current_user())['dir'];
      var_dump($home_dir); 
      

      Documentation

      【讨论】:

      • 它对我有用。我只想添加到您的答案$shell_user['dir'],因为主目录是问题主题。
      • $tmp = posix_getpwuid(getmyuid()); ; // Linux 安全 $home = $tmp['dir']."/" ;
      • 之所以没有特别提到$shell_user['dir']是因为我不确定数组变量命名是否适用于所有操作系统。
      • "posix_getpwnam(get_current_user())['dir'] 仍然返回当前用户在 Centos 7.7 上的主目录。只是为了让您知道人们是否正在搜索它并且正在运行基于 Centos 7网络服务器
      • 在posix中,您可以设置有效的UID(例如,代表用户以root身份工作),因此如果请求可能与有效的相关,您可能希望使用posix_geteuid而不是posix_getuid用户。如果尚未设置有效用户,它们会返回相同的内容,因此如果是这种情况,则不会造成伤害。
      【解决方案5】:

      这个函数取自Drush project

      /**
       * Return the user's home directory.
       */
      function drush_server_home() {
        // Cannot use $_SERVER superglobal since that's empty during UnitUnishTestCase
        // getenv('HOME') isn't set on Windows and generates a Notice.
        $home = getenv('HOME');
        if (!empty($home)) {
          // home should never end with a trailing slash.
          $home = rtrim($home, '/');
        }
        elseif (!empty($_SERVER['HOMEDRIVE']) && !empty($_SERVER['HOMEPATH'])) {
          // home on windows
          $home = $_SERVER['HOMEDRIVE'] . $_SERVER['HOMEPATH'];
          // If HOMEPATH is a root directory the path can end with a slash. Make sure
          // that doesn't happen.
          $home = rtrim($home, '\\/');
        }
        return empty($home) ? NULL : $home;
      }
      

      【讨论】:

        【解决方案6】:

        如果由于任何原因 getenv('HOME') 无法正常工作,或者服务器操作系统是 Windows,您可以使用 exec("echo ~")exec("echo %userprofile%") 获取用户目录。当然exec 功能必须可用(一些托管公司出于安全原因禁用了这种功能,但这种情况不太可能发生)

        这是一个函数,它将尝试$_SERVERgetenv,最后检查exec函数是否存在并使用适当的系统命令获取用户目录:

        function homeDir()
        {
            if(isset($_SERVER['HOME'])) {
                $result = $_SERVER['HOME'];
            } else {
                $result = getenv("HOME");
            }
        
            if(empty($result) && function_exists('exec')) {
                if(strncasecmp(PHP_OS, 'WIN', 3) === 0) {
                    $result = exec("echo %userprofile%");
                } else {
                    $result = exec("echo ~");
                }
            }
        
            return $result;
        }
        

        【讨论】:

        • 带有 shell-commands 的块很好,其余的是“二手”,可能不可靠。
        • @David 这只是一个获取主目录的函数;不知道你说的“二手”是什么意思;我知道我正在使用这个函数来检索 Windows 和 linux 中的主目录很长一段时间没有任何故障。什么不可靠?如果$_SERVER['HOME']getenv("HOME") 返回一个空的,就不会有主目录结果的事实?还是 PHP_OS 在 Windows 系统上以 WIN 开头?
        • 您已经明白了,建议今天的服务器尽可能少地暴露,并且通常没有配置或抑制“HOME”正在泄漏信息。此外,信息 - 如果可用 - 由服务器软件读取,然后以这种间接方式提供,因为它不是由系统直接读取的 - 所以理论上该值甚至可能是错误的。我在 Linux 上对其进行了测试,所以这不是操作系统问题。不过,我喜欢你的 sn-p 的后半部分,并用它来创建你的解决方案和 @Francisco Luz 的解决方案的合并版本,没有任何全局变量。
        • " 所以理论上这个值也可能是错误的" 我的意思是它可能是故意的
        • 事实上,这种方法只是大多数用户将/必须用于创建自己的自定义脚本的一段代码。脚本将运行的系统和这些系统将支持的环境是完全不同的故事,因此您不能说一段代码一般而言是不可靠的;也许它在某些情况案例下是不可靠的,但它的主要目的并非不可靠,即permission gnostic systems而不是共享第三方托管服务提供商服务器。具有 shell 访问权限的主机应该有不同的 CLI 安全设置。
        【解决方案7】:

        取决于你在哪里以及你想要做什么。

        $_SERVER 对于非服务器脚本完全不可靠,但 $_ENV['HOME'] 对于标准 shell 脚本可能更好。你可以随时print_r( $GLOBALS ) 看看你的环境让你玩什么。 phpinfo() 在从 CLI 脚本调用时也会吐出 plaintxt,而从 shell 执行的良好 ole php -i 也会这样做。

        【讨论】:

          【解决方案8】:

          这是我最近一个项目中使用的方法:

          exec('echo $HOME')
          

          我通过这样做将它保存到我的对象中:

          $this->write_Path  = exec('echo $HOME');
          

          但你真的可以以任何你想要的方式保存它,并以你认为合适的方式使用它。

          【讨论】:

          • 在某些 Centos 上无法使用,但在 Ubuntu LAMP 上可以使用
          【解决方案9】:

          在使用 Web 服务器时,您可以依赖“主”目录。如果你希望你的脚本在 web 和 cli 环境中工作,它会提供用户路径(在 Windows 中),我发现最好使用 dirname 提升任何级别,直到你的根(主)目录。

          echo dirname(__DIR__).PHP_EOL; // one level up
          echo dirname(dirname(__DIR__)); //two levels up
          echo dirname(__DIR__,2).PHP_EOL; //two levels only php >7.0
          

          【讨论】:

            【解决方案10】:

            $_SERVER['HOME'] 和 getenv('home') 对我不起作用。

            但是,在 PHP 5.5+ 上,这可以提供文件所在的主目录:

            explode( '/', __FILE__ )[2]
            

            【讨论】:

            • 这种方法的问题是用户主文件夹并不总是位于 /home/username。在共享主机上,它可能类似于 /home/storage/xxx/xxx/xxx/username
            【解决方案11】:

            尝试将$_SERVER['DOCUMENT_ROOT'] 作为您的主目录。

            【讨论】:

            • 欢迎来到 *。有空的时候请看看formatting explanation。谢谢。
            • 这是完全错误的。在几乎所有站点中,DocumentRoot !== $HOME。但是,OP 正在谈论 CLI,其中 $_SERVER['DOCUMENT_ROOT'] 甚至没有设置,因为它没有相关性。
            【解决方案12】:
            dirname(__DIR__);
            

            【讨论】:

            • 这只是一个脚本路径的目录。
            【解决方案13】:

            我知道这是一个老问题,但如果您正在寻找一种替代且易于在您的应用程序中复制的方法,您可以考虑使用通过 composer 安装的库。我已经编写了一个库,将这里的一些答案结合起来并使其成为一个库,我会在这里无耻地推广它:juliardi/homedir

            你可以通过 composer 安装它:

            $ composer require juliardi/homedir
            

            然后在你的应用程序中使用它:

            <?php
            
            require_once('vendor/autoload.php');
            
            $userHomeDir = get_home_directory();
            

            希望这个答案对你有所帮助。

            【讨论】: