Я подозреваю, что ваша проблема связана с частью sudo
командной строки nmap
. Если вы замените subprocess.call
на subprocess.check_call
, я думаю, вы найдете эта команда вызывает ошибку CalledProcessError
.
Предположительно, ваша учетная запись пользователя находится в файле /etc/sudoers
, а веб-сервер — нет.
Поскольку первое, что делает оператор перенаправления вывода оболочки (>
), — это усекает выходной файл, эта неудачная попытка запустить nmap
приводит к нулевому байту whohome.txt
. Затем остальная часть скрипта Python делает то же самое с website.txt
, и в итоге на вашем веб-сайте нечего отображать.
Решения
sudo
не требуется.
На моем рабочем столе Linux мне не нужно запускать nmap
от имени пользователя root для выполнения локального ping-сканирования. Если это так в вашей системе, то вы сможете просто удалить часть sudo
вашей команды nmap
и покончить с этим.
Однако есть разница. nmap
выполнит более тщательное тестирование каждой цели, когда root
запустит проверку связи -pS
. Со старой справочной страницы nmap
(выделено мной):
-sP
(пропустить сканирование портов).
[...]
Параметр -sP
по умолчанию отправляет эхо-запрос ICMP, TCP SYN на порт 443, TCP ACK на порт 80 и запрос метки времени ICMP. При выполнении непривилегированным пользователем на порты 80 и 443 адресата отправляются только пакеты SYN (с помощью вызова соединения). Когда привилегированный пользователь пытается сканировать цели в локальной сети ethernet, используются запросы ARP, если не указано --send-ip
. [...]
Включите sudo
для вашего веб-сервера.
Если вам нужна эта дополнительная информация (и похоже, что вам это нужно), вам нужно запустить nmap
(или скрипт Python, который его вызывает) с привилегиями суперпользователя. Я никогда не пытался заставить веб-сервер сделать это, но я предполагаю, что вам, по крайней мере, придется добавить пользователя вашего веб-сервера в /etc/sudoers
. Что-то вроде:
apache localhost=/usr/bin/nmap -sP
or:
httpd ALL=/usr/local/bin/nmap
... и так далее, в зависимости от имени пользователя, где находится ваш nmap
, насколько строго вы хотите ограничить аргументы до nmap
и т. д.
Создайте исполняемый файл SUID для запуска nmap
.
В качестве альтернативы (и я ненавижу себя за эту рекомендацию --- должен быть лучший способ) написать маленькую программу SUID (Set User ID), которая выполняет только nmap
команда, которую вы хотите. Вот программа на C, которая сделает это:
#include <stdio.h>
#include <unistd.h>
int main(void);
int main(void) {
int retval = 0;
char* const error_string = "ERROR: Failed to execute \"/usr/bin/map\"";
char* const nmap_args[] = {
"/usr/bin/nmap",
"-sP",
"192.168.1.0/24",
NULL
};
retval = execv("/usr/bin/nmap", nmap_args);
/* execv returns _only_ if it fails, so if we've reached this
* point, print an error and exit.
*/
perror(error_string);
return retval;
}
Сохраните приведенное выше как что-то вроде nmap_lan.c
и скомпилируйте с помощью:
$ gcc -Wall -o nmap_lan nmap_lan.c
Затем переместите его туда, где хранятся сценарии вашего веб-сайта, и от имени пользователя root измените его владельца и разрешения:
# chown root:root nmap_lan # Or whatever group name you use.
# chmod 4555 nmap_lan
Ведущий 4
устанавливает бит SUID. Цвет каталога ls
, вероятно, покажет, что этот файл выделен. Разрешения должны выглядеть так:
# ls -l nmap_lan
-r-sr-xr-x. 1 root root 6682 May 23 03:04 nmap_lan
Любой пользователь, запускающий nmap_lan
, будет временно повышен до владельца файла nmap_lan
(в данном случае root
) до выхода из программы. Это чрезвычайно щедро, поэтому я жестко запрограммировал все в этой программе... Чтобы изменить что-либо, что она делает --- даже диапазон IP-адресов для сканирования --- вам придется отредактировать nmap_lan.c
файл, перекомпилировать и переустановить.
Я протестировал nmap_lan
в своей командной строке, и он выдает вывод привилегированного пользователя nmap
при запуске непривилегированным пользователем, который обычно получает только ограниченный вывод.
Комментарии к скрипту Python
В общем, Python намного лучше анализирует аргументы оболочки, чем сама оболочка (значение по умолчанию для shell
равно False
по какой-то причине), поэтому ваш сценарий Python должен выполнять как можно больше работы, включая разбор команды оболочки, перенаправление ввода и перенаправление вывода.
Основное преимущество выполнения работы на Python заключается в том, что невозможность открыть, прочитать, записать или закрыть любой из ваших файлов приведет к немедленному сбою и трассировке стека --- вместо тихого сбоя, с которым вы сталкивались.
Я бы переписал эту команду call
, чтобы использовать список явно разделенных аргументов. Вы можете обрабатывать перенаправление вывода, передав открытый файловый поток параметру stdout
. Вы можете избавиться от последней части перенаправления оболочки, заставив Python открыть выходной файл и явно записать в него.
nmap_file='/home/pi/whohome.txt'
with open(nmap_file, 'wt', encoding='ascii') as fout:
subprocess.call(
['/usr/bin/nmap', '-sP', '192.168.1.0/24'], # Or just ['nmap_lan']
stdout=fout,
universal_newlines=True,
)
output_file='/var/www/html/website.txt'
with open(nmap_file, 'rt', encoding='ascii') as fin:
with open(output_file, 'wt', encoding='ascii') as fout:
for line in fin:
...
print('Output here', file=fout) # Add `file=...` to each print.
Кроме того, если вам не нужен этот файл whohome.txt
для чего-то другого, вы можете полностью удалить его, используя check_output
, чтобы сохранить вывод команды nmap
в виде строки, а затем разбить ее на отдельные строки. (Параметр universal_newlines
также обрабатывает преобразование объекта bytes
в str
, по крайней мере, в Python 3.)
lines = subprocess.check_output(
['/usr/bin/nmap', '-sP', '192.168.1.0/24'], # Or just ['nmap_lan']
universal_newlines=True
).split('\n')
output_file='/var/www/html/website.txt'
with open(output_file, 'wt', encoding='ascii') as fout:
for line in lines:
...
print('Output here', file=fout) # Add `file=...` to each print.
Обратите внимание, что я использовал блоки with
, чтобы закрыть файл бесплатно.
(Наконец, эта последовательность команд if
требует перезаписи в виде цикла for machine in machines_dict:
, в котором строки, которые вы ищете, являются ключами в этом словаре, а вывод, который вы хотите распечатать, — значениями.)
person
Kevin J. Chase
schedule
23.05.2016
website.txt
оказывается пустым (или кажется пустым). Проверьте контекст безопасности файла с помощьюls -Z *whatever*
. - person Kevin J. Chase   schedule 23.05.2016website.txt
усекается до 0 байт при перезагрузке страницы? Это будет означать, что скрипт python работает, но выдает 0 байтов вывода. Есть ли какие-либо полезные данные в файлеwhohome.txt
? - person Kevin J. Chase   schedule 23.05.2016chmod
изменили на0777
, и в целом повторно включить любую защиту, которую вы отключили при устранении неполадок. - person Kevin J. Chase   schedule 23.05.2016