Table of Contents

Немного о самой программе

Думаю, что каждому пользователю UNIX-подобных систем знакома утилита neofetch и её аналоги (pfetch,screenfetch и некоторые другие). Эта маленькая программа позволяет вывести информацию о системе и аппаратной части компьютера в удобном формате.

Neofetch есть в большинстве дистрибутивов, (и даже есть возможность установки в windows и haiku), да и собрать из исходников никто не мешает.

K примеру в ubuntu она ставиться следующим образом:

sudo apt update
sudo apt install neofetch

neofetch_pro

На гифке выше - neofetch выводит название ОС, имя хоста, shell, разрешение экрана, оконный менеджер, gtk тему, иконки и название терминала. Чуть ниже расположена полоска с цветами, отображающая цветовую схему терминала. Однако можно вывести куда больше информации, и на этом этапе вы можете начать разбираться с конфигурационным файлом. Как правило он лежит в директории ~/.config/neofetch . Если такой директории нет, то создайте её и в ней пропишите конфиг в файле config.conf.

vim ~ /.config/neofetch/config.conf

Однако мне захотелось сделать свою версию на python. И для начала я отправился на github и нашёл там уже готовое решение,правда для MacOs. И естественно оно не заработало на linux, даже не смотря то, что это схожие системы с точки зрения UNIX. И потому было принято решение переписать эту программу.

Я не стал менять архитектуру скрипта, а просто изменил системные вызовы , подходящиe для linux систем.

Модули

Локальный ip адрес

Давайте определим локальный ip адрес. Сделаем мы это при помощи модуля socket.

Создаём функцию local_ip, ищем локальный адрес, открывая localhost и перебирая порты. Функция сохраняет значение, которые в последствии мы выведем пользователю на экран. Если же по каким-то причинам нам это не удалось, то функция сохраняет значение None.

По такому же принципу работают и остальные модули, которые обозначены ниже.

def local_ip():
   try:
       s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
       s.connect(("8.8.8.8", 80))
       return s.getsockname()[0]
   except:
       return None

Имя хоста

В функции host_name через socket.gethostname() определяем имя хоста.

def host_name():
    try:
        return socket.gethostname()
    except:
        return None

Операционная система

Чтобы определить операционную систему воспользуемся специальной библиотекой - platform.

def os_version():
    try:
        return platform.linux_distribution(distname='', version='', id='', supported_dists=('SuSE', 'debian', 'redhat', 'mandrake', ...), full_distribution_name=1)


    except:
        return None

Разрешение экрана

Давайте теперь узнаем разрешение экрана. Сделаем мы это при помощи библиотеки subprocess, которой мы воспользуемся ещё не раз. Главным для нас являтся subprocess.check_output , который позволяет прямо из python выполнять команды sh. Чтобы выяснить разрешение в терминале можно ввести команду :

xrandr

А в своём python скрипте мы напишем следущее:

def screen_size():
    try:
        return subprocess.check_output(["xrandr | grep \"*\""], shell=True)
    except:
        return None

Однако в выводе терминала мы получаем следущее

 b'   1280x1024     60.02*+  75.02  \n'

На мой взгляд это выглядит некрасиво. Потому давайте поправим эту ситуацию. Мы просто декодируем вывод в удобо-читаемый формат.

.decode('utf-8')

Итоговая конструкции выглядит следующим образом:


def screen_size():
    try:
        return subprocess.check_output(["xrandr | grep \"*\""], shell=True).decode('utf-8')
    except:
        return None

Uptime

Через тот же модуль узнаем uptime - время проведённое за текущей сессией. Команда uptime выведет нам крайне много информации, которая на мой взгляд лишняя. Потому я добавил префикс -p , что является сокращением от pretty. Основываясь на опыте написания предыдущего модуля, добавляем .decode(‘utf-8’).

def uptime():
    try:
        return subprocess.check_output(["uptime -p"], shell=True).decode('utf-8')
    except:
        return None

Shell

Название shell узнаем при помощи библиотеки os.

def shell():
    try:
        return os.environ.get('SHELL', '')
    except:
        return None

Ядро

Версию ядра можно вывести при помощи platform - библиотеки,которая может нам рассказать много интересного об установленном билде python, платформе на которую установлен язык. Также эта библиотека может показать нам версию ядра, и неважно будет оно “ванильным” или пропатченным каким-либо мейнтейнером.

def kernel():
    try:
        return platform.release()
    except:
        return None

Архитектура процессора

Скажу честно, адекватно выводить название процессора и его поколение я не научился (я работаю над этим). Однако без каких-либо проблем я могу выводить название архитектуры процессора. Так как в наличии у меня только компьютер с архитектурой x86_64, то и тестировалась эта функция на предмет вывода x86_64. Если у вас есть устройства на базе других архитектур: arm, powerpc и прочих, то прошу вас протестировать. В случае проблем откройте тикет на github в соотвествующем репозитории.

def cpu_spec():
    try:
        return platform.processor()
    except:
        return None

DE/WM

Теперь выведем Desktop environment(DE) и window manager(WM). os.environ.get() позволит нам узнать, что же у нас за окружение.

def de():
    try:
        return os.environ.get('DESKTOP_SESSION')
    except:
        return None

Шаблон

Теперь самое вкусное - шаблон. Здесь в виде ascii мы нарисуем пингвинчика Tux - символа linux, гапсы для вывода информации,которыю мы собирали модулями, а также цветовую палитру.

Создаём константу TEMPLATE в которой мы выводим информацию на экран. Однако вы зададитесь вопросом, что за \033[92m . А я вам отвечу - это комманда позволяющая окрашивать терминал в различные цвета. Она работает и без python, можете попробовать её в своём терминале. Её используют для проверки цветового покрытия терминала . Можете почитать об этом подробнее тут .

 TEMPLATE = """

\033[92m       a88888.       {hostname} \033[0m
\033[92m      d888888b.   \033[0m   {hostname_sep}
\033[92m      d888888b.   \033[0m\033[93m  OS: {os_version}
\033[92m      8P"YP"Y88   \033[0m\033[93m  Kernel:{kernel}
\033[93m      8|o||o|88   \033[0m\033[93m  Cpu architecture: {cpu}
\033[93m      8'    .88   \033[0m\033[93m  Shell: {shell}
\033[93m      8'    .88   \033[0m\033[93m  DE(WM): {de}
\033[93m      8`._.' Y8   \033[0m\033[93m  Uptime: {uptime}
\033[91m     d/      `8b. \033[0m\033[93m  Resolution: {size}
\033[91m   .dP   .     Y8b\033[0m\033[93m  Local IP: {local_ip}
\033[91m   d8:'   "   `::88b.
\033[95m  d8"           `Y88b
\033[95m :8P     '       :888
\033[95m  8a.    :      _a88
\033[94m  ._/"Yaa_ :    .| 88P|
\033[94m   \    YP"      `| 8P  `.
\033[94m  /     \._____.d|    .'
\033[94m  `--..__)888888P`._.'

\033[30m███\033[0m\033[91m███\033[0m\033[92m███\033[0m\033[93m███\033[0m\033[94m███\033[0m\033[95m███\033[0m\033[96m███\0
"""

Вывод информации

Ну и на последок нам стоит привести выше изложенный template в работоспособное состояние. Просто обозначаем команду вывода в которой указываем что хотим вывести - сохранённые значения функций и сепаратор.

print(TEMPLATE.format(hostname = host_name(),
       hostname_sep = "-" * len(host_name()),
       os_version=os_version(),
       kernel=kernel(),
       cpu=cpu_spec(),
       shell=shell(),
       de=de(),
       uptime=uptime(),
       size=screen_size(),
       local_ip=local_ip()
 ))

И что в итоге?

Сохранив скрипт и запустив его, мы получаем следующий результат:

Ну и по традиции прилагаю репозиторий на GitHub’е .