Использование команд операционной системы
Операционная система содержит большое количество команд, которые пользователь может выполнить из командной строки. Например, если необходимо вывести список файлов каталога или скопировать файл, в Windows можно воспользоваться командами dir и сору, а в Unix/Linux — ls и ср. (Для доступа к консольному окну, позволяющему работать с командной строкой в операционной системе Windows 2000, нужно выбрать следующую команду меню: Start=>Programs=>Accessories=>Command Prompt (Пуск=>Программы=>Стандартные=>Командная строка.) Предполагается, что вы знакомы с синтаксисом и назначением системных команд используемой операционной системы. В данном разделе рассказывается о том, как запустить команды операционной системы из сценария РНР. В РНР имеется множество функций, предназначенных для выполнения тех или иных действий. Например, содержимое каталога можно считать с помощью функций opendir() и readdir() (см. предыдущий раздел), а файлы можно скопировать с использованием функции сору(). Однако в некоторых случаях может потребоваться выполнить некоторые действия, для которых не существует специальных функций РНР. Например, иногда нужно скопировать каталог со всем его содержимым, просмотреть или изменить текущий путь, очистить экран и т.д. В некоторых случаях может оказаться, что проще использовать команды операционной системы, например ls или dir, чем встроенные функции РНР — opendir или readdir. Вам также может понадобиться вызвать программу, написанную на другом языке программирования, например на Perl. Нет проблем! Все эти задачи можно легко решить с помощью РНР.
Сообщения об ошибках при вызове системных команд
Ни один из используемых методов РНР для вызова системных команд не поддерживает вывод или возврат сообщений при ошибках. Вы знаете, что системная команда не сработала, поскольку не получили нужный результат. Но что именно не так — неизвестно.
Для вывода сообщений об ошибках при несрабатывании системной команды необходимо добавить несколько символов в строку вызова. Таковыми для большинства операционных систем являются 2>&1. Рассмотрим следующий пример:
$result = system("di c:\php"); В данном случае функция system() используется для вывода содержимого каталога c:\php, но системная команда dir написана с ошибкой. Не существует такой команды, как di, соответственно ничего выведено не будет. Добавим нужные символы:
$result = system("di c:\php 2>&1"); В этом случае отобразится сообщение об ошибке. В операционной системе Windows 2000 оно будет иметь следующий вид:
'di' is not recognized as an internal or external command, operable program or batch file
Заметьте, что набор символов 2>&1 используется без пробелов. |
Для вызова системных команд или внешних программ в РНР предусмотрены следующие методы:
- Обратные одинарные кавычки (' '). Для вызова системной команды ее имя можно заключить в обратные одинарные кавычки, и результат работы отобразится на экране.
- Функция system(). Вызывает команду операционной системы, выводит результат выполнения на экран и возвращает последнюю строку вывода.
- Функция exec(). Вызывает команду операционной системы, результат выполнения сохраняет в массиве и возвращает последнюю строку результата выполнения.
- Функция passthru(). Вызывает системную команду и отображает результат выполнения на экране.
В общем случае РНР позволяет вызывать любые команды. При этом они будут выполняться точно так же, как если бы они были вызваны непосредственно из командной строки операционной системы. Можно вызывать простые команды, такие как ls или dir, rename или mv, rm или del, можно перенаправлять результаты выполнения, вызывать две команды в одной строке и т.д., т.е. вся функциональность, которая поддерживается операционной системой, может быть доступна и в сценариях РНР. Ниже приводятся примеры системных команд, которые можно вызвать из кода РНР.
dir rm badfile.txt dir | sort cd c:\php ; dir (Недоступна в Windows) "cd c:\php && dir" (Для Windows 2000) dir > dirfile sort < unsortedfile.txt
Иногда процесс выполнения системной команды занимает большой промежуток времени. РНР позволяет вызвать команду в фоновом режиме (если, конечно, используемая операционная система поддерживает его), в то время как сценарий РНР будет продолжать выполняться. В этом случае результат вызова системной команды необходимо перенаправить в отдельный файл, а не сохранять в переменной сценария.
Рассмотрим теперь различные методы вызова команд операционной системы из РНР более подробно.
Использование одинарных кавычекСамый простой способ вызвать системную команду из РНР — поместить ее в обратные одинарные кавычки. Например:
$result = dir ‘c:\php4‘; Переменная $result будет содержать результат выполнения команды dir , т.е. информацию о содержимом каталога с:\php:
Volume in drive C has no label. Volume Serial Number is 394E-15E5
Directory of c:\php 02/25/2009 10:48a <DIR> . 02/25/2009 10:48a <DIR> .. 02/25/2009 04:30p <DIR> dev 02/25/2009 04:30p <DIR> ext 02/25/2009 04:30p <DIR> extras 02/25/2009 04:30p 417,792 fdftk.dll 02/25/2009 04:30p 90,112 fribidi.dll 02/25/2009 04:30p 346,624 gds32.dll 02/25/2009 04:30p 70 go-pear.bat 02/25/2009 04:30p 32,081 install.txt 02/25/2009 04:30p 876,544 libeay32.dll 02/25/2009 04:30p 47,027 libintl-l.dll 02/25/2009 04:30p 165,643 libmhash.dll 02/25/2009 04:30p 233,472 libmysql.dll 02/25/2009 04:30p 3,208 license.txt 02/25/2009 04:30p 57,344 msql.dll 02/25/2009 04:30p 18,151 news.txt 02/25/2009 04:30p 278,800 ntwdblib.dll 02/25/2009 04:30p <DIR> PEAR 02/25/2009 04:30p 53,248 php-cgi.exe 02/25/2009 04:30p 28,672 php-win.exe 02/25/2009 04:30p 28,672 php.exe 02/25/2009 04:30p 3,872 php.gif 02/25/2009 04:30p 39,284 php.ini-dist 02/25/2009 04:30p 40,899 php.ini-recommended 02/25/2009 04:30p 40,960 php5activescript.dll 02/25/2009 04:30p 36,864 php5apache.dll 02/25/2009 04:30p 36,864 php5apache2.dll 02/25/2009 04:30p 53,248 php5apache_hooks.dll 02/25/2009 04:30p 503,320 php5embed.lib 02/25/2009 04:30p 28,672 php5isapi.dll 02/25/2009 04:30p 28,672 php5nsapi.dll 02/25/2004 04:30p 3,452 php5ts.dll 02/25/2004 04:30p 1,224 snapshot.txt 02/25/2004 04:30p 159,744 ssleay32.dll 02/25/2004 04:30p 49,152 php_mysql.dll 30 File(s) 7,153,163 bytes 6 Dir(s) 251,727,872 bytes free Обратные одинарные кавычки можно использовать в том случае, когда режим safe_mode отключен, т.е. соответствующая переменная имеет значение Off (это значение используется по умолчанию при установке РНР).
Использование функции system()Функция system() выполняет системную команду, выводит результат, ее выполнения на экран и возвращает последнюю строку вывода. Рассмотрим следующий пример:
$result = system("dir c:\php"); В результате вызова функции system() отобразится содержимое каталога c:\php, а переменная $result будет содержать последнюю строку вывода:
11 Dir(s) 566,263,808 bytes free
Использование функции exec()Функция exec() выполняет системную команду, но при этом не выводит результат выполнения на экран. Однако он может быть сохранен в массиве, значения элементов которого — строки, сформированные в результате вызова команды операционной системы. Как и функция system(), exec() возвращает последнюю строку.
Пусть, например, необходимо узнать, сколько файлов и свободного дискового пространства содержится в каталоге. Для этого можно воспользоваться функцией exec() следующего вида:
$result = exec("dir c:\php" ); После выполнения этой функции на экран ничего не будет выведено, а переменная $result будет содержать последнюю строку результата вызова системной команды dir:
11 Dir(s) 566,263,808 bytes free Если же необходимо сохранить весь результат выполнения команды dir, следует воспользоваться следующим форматом функции exec():
$result = exec("dir c:\php", $dirout); В результате выполнения этой функции в массив $dirout будут помещены строки с информацией о содержимом каталога с:\php. Для вывода всех элементов массива воспользуемся следующим фрагментом кода:
foreach($dirout as $line) { echo "$line\n"; }
В результате получим следующую информацию: Volume in drive C has no label. Volume Serial Number is 394E-15E5
Directory of c:\php 02/25/2009 10:48a <DIR> . 02/25/2009 10:48a <DIR> .. 02/25/2009 04:30p <DIR> dev 02/25/2009 04:30p <DIR> ext 02/25/2009 04:30p <DIR> extras 02/25/2009 04:30p 417,792 fdftk.dll Для вывода значений определенных элементов массива $dirout можно воспользоватьсяследующим фрагментом кода:
echo $dirout[3]; echo $dirout[7];
В результате будут выведены такие строки: Directory of c:\php 02/25/2009 04:30p <DIR> dev
Использование функции passthru()Функция passthru() предназначена для вызова системной команды и отображения результата ее выполнения на экране. Например:
passthru("dir c:\php"); Она просто выводит результат на экран и ничего не возвращает. При этом результат выполнения системной команды никак этой функцией не обрабатывается и поэтому может использоваться для вывода двоичных строк.
Вопросы безопасности
Вызывая системную команду, вы позволяете пользователю выполнять определенные действия на вашем компьютере. Например, системная команда dir с:\php вполне безобидна, в то время как вызов команды rm/bin/* или del с:\*.* может привести к непоправимым последствиям. Поэтому следует быть осторожным при использовании функций, позволяющих выполнять команды операционной системы.
Когда вы создаете сценарий РНР, в котором сами выполняете команды типа dir или ls, — ситуация под контролем. Но если для вызова системных команд используются данные, полученные от пользователей, необходимо соблюдать особую осторожность. Рассмотрим такой пример. Предположим, имеется приложение, которое на основе введенного имени пользователя создает соответствующий каталог. Пусть пользователь в поле directoryName некоторой формы ввел свое имя Smith. Для обработки введенной информации можно воспользоваться следующим фрагментом кода:
$directoryName = $_POST['directoryName']; exec("mkdir $directoryName");
Поскольку переменная $directoryName имеет значение Smith, то в результате выполнения команды exec("mkdir $directoryName") будет создан каталог с именем Smith. Казалось бы, все нормально.
Однако предположим, что пользователь ввел в поле формы следующую строку: Smitn; rm *. В этом случае $directoryName = Smith; rm * и будет выполнен такой набор команд: mkdir Smith; rm *. Во многих операционных системах, таких как Unix/Linux, символ точки с запятой используется для разделения команд в одной строке, т.е. выражение mkdir Smith; rm * эквивалентно
mkdir Smith rm *
А вот это действительно проблема. Сначала будет создан каталог с именем Smith, но потом все файлы в текущем каталоге будут уничтожены!
Все это говорит о том, что следует быть крайне осторожным при вызове команд, содержащих параметры. Необходимо четко понимать, откуда поступает такая команда. Если это данные, полученные от пользователя, их необходимо проверить на корректность. Так, в предшествующем примере можно было бы проверить значение поля формы, чтобы оно содержало только буквы и числа.
|