diff --git a/features/shell.feature b/features/shell.feature index d5595506..26f05137 100644 --- a/features/shell.feature +++ b/features/shell.feature @@ -61,6 +61,38 @@ Feature: WordPress REPL """ And STDERR should be empty + Scenario: Use SHELL environment variable as fallback for bash + Given a WP install + + And a session file: + """ + return true; + """ + + # SHELL pointing to bash should work (when bash is available). + When I try `SHELL=/bin/bash wp shell --basic < session` + Then STDOUT should contain: + """ + bool(true) + """ + And STDERR should be empty + + # SHELL pointing to non-bash binary should be ignored and fall back to /bin/bash. + When I try `SHELL=/bin/sh wp shell --basic < session` + Then STDOUT should contain: + """ + bool(true) + """ + And STDERR should be empty + + # SHELL pointing to invalid path should be ignored and fall back to /bin/bash. + When I try `SHELL=/nonsense/path wp shell --basic < session` + Then STDOUT should contain: + """ + bool(true) + """ + And STDERR should be empty + Scenario: Input starting with dash Given a WP install And a session file: diff --git a/src/WP_CLI/Shell/REPL.php b/src/WP_CLI/Shell/REPL.php index 99b8f1f8..52af4139 100644 --- a/src/WP_CLI/Shell/REPL.php +++ b/src/WP_CLI/Shell/REPL.php @@ -122,8 +122,15 @@ private static function create_prompt_cmd( $prompt, $history_path ) { $history_path = escapeshellarg( $history_path ); if ( getenv( 'WP_CLI_CUSTOM_SHELL' ) ) { $shell_binary = getenv( 'WP_CLI_CUSTOM_SHELL' ); - } else { + } elseif ( is_file( '/bin/bash' ) && is_readable( '/bin/bash' ) ) { + // Prefer /bin/bash when available since we use bash-specific commands. $shell_binary = '/bin/bash'; + } elseif ( getenv( 'SHELL' ) && self::is_bash_shell( getenv( 'SHELL' ) ) ) { + // Only use SHELL as fallback if it's bash (we use bash-specific commands). + $shell_binary = getenv( 'SHELL' ); + } else { + // Final fallback for systems without /bin/bash. + $shell_binary = 'bash'; } if ( ! is_file( $shell_binary ) || ! is_readable( $shell_binary ) ) { @@ -144,6 +151,21 @@ private static function create_prompt_cmd( $prompt, $history_path ) { return "{$shell_binary} -c " . escapeshellarg( $cmd ); } + /** + * Check if a shell binary is bash or bash-compatible. + * + * @param string $shell_path Path to the shell binary. + * @return bool True if the shell is bash, false otherwise. + */ + private static function is_bash_shell( $shell_path ) { + if ( ! is_file( $shell_path ) || ! is_readable( $shell_path ) ) { + return false; + } + // Check if the basename is exactly 'bash' or starts with 'bash' followed by a version/variant. + $basename = basename( $shell_path ); + return 'bash' === $basename || 0 === strpos( $basename, 'bash-' ); + } + private function set_history_file() { $data = getcwd() . get_current_user();