Issue Write-up: PHP getcwd() reports /usr/local/emhttp when run from CLI, causing Git “Not a repository” error.

The Symptom

When executing a PHP script from the command line interface (CLI) within a specific directory (e.g., a Git repository directory), the getcwd() function reports a different, unexpected directory (/usr/local/emhttp).

This mismatch causes relative shell commands run via shell_exec(), especially git commands, to fail with the error:

fatal: not a git repository (or any parent up to mount point /)

Example of the confusing output:

<em># User is here:</em>
root@unraid:/mnt/user/WORK/myUNRAID/docker-runs# php get-docker-runs.php 

<em># Script reports its location as:</em>
wdir:/usr/local/emhttp 
fatal: not a git repository ...

The Root Cause (Specific to Unraid OS)

The issue is not a bug in PHP, a shell alias, or a standard configuration setting.
It is caused by a specific configuration directive in Unraid’s php.ini file:

auto_prepend_file = /usr/local/emhttp/webGui/include/local_prepend.php

This directive forces PHP to execute the specified file (local_prepend.phpbefore your user script starts. The code inside local_prepend.php contains a chdir('/usr/local/emhttp'); call, which changes the PHP script’s current working directory immediately upon startup.

By the time your script’s code runs, PHP has already been moved to the Unraid web GUI root folder, regardless of where you initiated the script from the command line.

The Solution

To run Git commands correctly from your specific repository directory, you must explicitly change the working directory back to your desired location within your PHP script, after the auto-prepend file has executed.

Use the chdir() function at the top of your script to force the correct working directory:

php

<?php
<em>// Define the actual location of your Git repository</em>
$repo_path = '/mnt/user/WORK/myUNRAID/docker-runs';

<em>// Change directory to the repository path</em>
if (!chdir($repo_path)) {
    echo "ERROR: Could not change directory to repository path: $repo_path\n";
    exit(1);
}

<em>// Now all subsequent shell commands (like git status, git pull)</em>
<em>// will execute from the correct directory.</em>
$output = shell_exec('git rev-parse --abbrev-ref HEAD');
echo "Git command successful. Branch: $output\n";
?>

Here are the best ways to achieve a dynamic, reusable script:

Method 1: Use __DIR__ or $_SERVER['SCRIPT_FILENAME'] 

The magic constant __DIR__ always returns the directory containing the currently executing script file, regardless of what the current working directory (getcwd()) has been changed to by the Unraid prepender.

php

<?php
<em>// __DIR__ provides the directory where THIS file lives, e.g., /mnt/user/WORK/myUNRAID/docker-runs</em>
$script_location = __DIR__; 
<em>// or alternatively use $_SERVER['SCRIPT_FILENAME'] for a slightly more robust path</em>
<em>// $script_location = dirname($_SERVER['SCRIPT_FILENAME']);</em>


<em>// Change PHP's current working directory to where the script is located</em>
if (!chdir($script_location)) {
    echo "ERROR: Failed to change directory to script location: $script_location\n";
    exit(1);
}

<em>// Now the Git commands work dynamically, no hardcoded path needed</em>
$branch = shell_exec('git rev-parse --abbrev-ref HEAD');
$hash   = shell_exec('git log -1 --pretty=format:%h');

echo "Branch: $branch";
echo "Hash: $hash";
?>

Use code with caution.

Method 2: Use Git’s -C flag dynamically (The cleanest for Git operations)

This method doesn’t require changing PHP’s working directory at all. It uses the git -C <path> command option to tell Git where to run the command from. __DIR__ provides the dynamic path.

php

<?php
<em>// This works dynamically without needing chdir() first</em>
$repo_path = __DIR__; 

$branch_command = "git -C $repo_path rev-parse --abbrev-ref HEAD 2>&1";
$hash_command   = "git -C $repo_path log -1 --pretty=format:%h 2>&1";

$branch = shell_exec($branch_command);
$hash   = shell_exec($hash_command);

echo "Branch: $branch";
echo "Hash: $hash";
?>

Use code with caution.

Summary

By using the __DIR__ magic constant, your script automatically finds its own location on the filesystem, effectively bypassing the initial chdir() command issued by the Unraid prepender script and making your script portable and reusable across different repositories.

Leave a Reply