Как запустить PHP-скрипт в одну строку и передать аргументы командной строки с помощью bash?

Вопрос или проблема

Я пытаюсь создать простой скрипт, который отправляет ping на сетевое соединение:

#!/usr/bin/env bash

# Обнаружение IP для Xdebug в Docker
# Авторские права (C) 2023 Димитриос Десиллас
#
# Эта программа является свободным программным обеспечением: вы можете распространять её и/или изменять
# в соответствии с условиями Стандартной общественной лицензии GNU, опубликованной
# Фондом свободного программного обеспечения, либо версии 3 лицензии, либо
# (по вашему выбору) любой последующей версии.
#
# Эта программа распространяется в надежде, что она будет полезна,
# но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ; даже без подразумеваемых гарантий
# ПРИГОДНОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ или ТОВАРНОЙ ПРИГОДНОСТИ. Подробности смотрите в
# Стандартной общественной лицензии GNU.
#
# Вы должны были получить копию Стандартной общественной лицензии GNU
# вместе с этой программой. Если нет, см. <https://www.gnu.org/licenses/>.

SCRIPT=$(cat << 'EOM'
<?php

define('ERROR',"\033[0;31m");
define('OK',"\033[0;32m");
define('HIGILIGHT',"\033[0;96m");
define('HIGILIGHT2',"\033[1;33;4;44m");
define('HIGILIGHT_ERROR',"\033[0;95m");

define('NC',"\033[0m");

if(count($argv) < 2){
    echo HIGILIGHT_ERROR." No IP and port provided".NC.PHP_EOL;
    exit(-1);
}

$host = $argv[1];

$host_parts = explode(":",$host);

$host = $host_parts[0];

if(isset($host_parts[1])){
    $port=$host_parts[1];
} elseif(isset($argv[2])){
    $port = $argv[2];
} else {
    echo HIGILIGHT_ERROR." No port provided".NC.PHP_EOL;
    exit(-1);
}

$port = intval($port);

$timeout = 30;

echo PHP_EOL."##############".PHP_EOL.PHP_EOL."TESTING ".HIGILIGHT2.$host.':'.$port.NC.PHP_EOL;

//проверяем, установлено ли соединение через is_resource
$sk = @fsockopen($host, $port, $errnum, $errstr, $timeout);
if (!is_resource($sk)) {
    echo ERROR."connection fail: ".HIGILIGHT_ERROR. $errnum . " " . $errstr.NC.PHP_EOL;
    exit(1);
} else {
    echo OK."Connected".NC.PHP_EOL;
    exit(0);
}
EOM
)

echo "$SCRIPT" | php -d xdebug.mode=off $@
exit $?

Но как только я его выполняю:

bash check_connect 172.162.5.3:3306

Я получаю:

Could not open input file: 172.162.5.3:3306

Как я могу также использовать конвейер и аргументы командной строки в моем скрипте?

Вы можете запустить php -- arguments

например:

#!/bin/sh

S='<?php
printf("You entered %s\n",$argv[1]);
?>'

echo $S | php -- hello

вернет вывод

You entered hello

Ответ или решение

Запуск PHP-скриптов непосредственно внутри оболочки Bash с поддержкой передачи аргументов командной строки является полезным навыком для IT-специалистов, особенно когда необходимо быстро запускать сетевые проверки или выполнять другие автоматизированные задачи из скриптов. Для этого важно чётко понять, каким образом данные передаются между Bash и PHP, поскольку некоторые ошибки могут возникнуть из-за неправильной интерпретации или передачи входных данных.

Теоретическая основа

PHP достаточно гибок и может исполняться без необходимости создания отдельных файлов, что делает его удобным для инлайновых скриптов. При работе с командной строкой, PHP предоставляет глобальный массив $argv, который содержит список всех аргументов, переданных скрипту. Первый элемент массива $argv[0] всегда является именем файла скрипта, а последующие элементы — это переданные параметры. В Bash, командная строка поддерживает передачу аргументов скрипту при помощи переменных $@, которые автоматически собирают все аргументы, переданные скрипту.

Пример применения

Рассмотрим пример скрипта, в котором Bash используется для запуска инлайнового PHP-скрипта, предназначенного для тестирования сетевого соединения. В этом случае важно правильно передать аргументы так, чтобы PHP смог их корректно обработать. Основной проблемой вашего текущего кода является попытка передать параметры из Bash в PHP, когда последний ожидает входные данные через стандартный ввод (STDIN), что приводит к ошибке «Could not open input file».

Корректное применение

Вот как можно исправить скрипт, чтобы он правильно передавал аргументы:

#!/usr/bin/env bash

# Определение PHP-скрипта как строки
SCRIPT=$(cat << 'EOM'
<?php

define('ERROR',"\033[0;31m");
define('OK',"\033[0;32m");
define('HIGHLIGHT',"\033[0;96m");
define('HIGHLIGHT2',"\033[1;33;4;44m");
define('HIGHLIGHT_ERROR',"\033[0;95m");

define('NC',"\033[0m");

if(count($argv) < 2){
    echo HIGHLIGHT_ERROR." No IP and port provided".NC.PHP_EOL;
    exit(-1);
}

$host = $argv[1];

$host_parts = explode(":",$host);

$host = $host_parts[0];

if(isset($host_parts[1])){
    $port=$host_parts[1];
} elseif(isset($argv[2])){
    $port = $argv[2];
} else {
    echo HIGHLIGHT_ERROR." No port provided".NC.PHP_EOL;
    exit(-1);
}

$port = intval($port);

$timeout = 30;

echo PHP_EOL."##############".PHP_EOL.PHP_EOL."TESTING ".HIGHLIGHT2.$host.':'.$port.NC.PHP_EOL;

$sk = @fsockopen($host, $port, $errnum, $errstr, $timeout);
if (!is_resource($sk)) {
    echo ERROR."Connection fail: ".HIGHLIGHT_ERROR. $errnum . " " . $errstr.NC.PHP_EOL;
    exit(1);
} else {
    echo OK."Connected".NC.PHP_EOL;
    exit(0);
}
EOM
)

# Передача аргументов
echo "$SCRIPT" | php -- $@
exit $?

Применение решений

При запуске данного скрипта через терминал, например, командой:

bash check_connect.sh 172.162.5.3:3306

аргументы будут корректно переданы в PHP-скрипт, который, в свою очередь, выполнит проверку соединения по заданному IP и порту.

Дополнительные советы

  1. Отладка: Если возникает ошибка в работе скрипта, попробуйте добавить вывод отладочных сообщений, чтобы видеть, какие именно данные передаются в PHP. Это можно сделать, добавив команды echo в Bash и var_dump() или print_r() в PHP.

  2. Безопасность: Всегда проверяйте вводимые данные на безопасность, особенно если скрипты планируется использовать в производственной среде. Это важно для защиты от атак, таких как инъекции.

  3. Документирование: Документируйте каждый шаг скрипта, указывая, какие именно переменные и функции используются и почему. Это облегчит понимание вашего кода другими разработчиками или самим вами через некоторое время.

С данном подходом вы можете существенно расширить возможности своих Bash-скриптов, делая их более гибкими и функциональными.

Оцените материал
Добавить комментарий

Капча загружается...