Голанг запускает команду linux

Обновлено: 01.07.2024

Go уже готов на 99% На самом деле, вы уже можете писать скрипты на Go. Используя подкоманду run Go: если у вас есть скрипт с именем my-script.go, вы можете просто запустить его с помощью go run my-script.go. Я думаю, что на этом этапе команде go run нужно уделить немного больше внимания.

Как запустить основной файл?

Вы можете создать программу Go в любом месте вашей системы. Типичная программа Go представляет собой обычный текстовый файл с расширением .go. Вы можете запустить эту программу с помощью команды go run hello.go, где hello.go — это файл программы Go в текущем каталоге.

Как запустить несколько файлов?

Запуск кода с несколькими файлами в одном основном пакете в GoLang

  1. беги *.go. В некоторых операционных системах *nix, включая Linux и MacOS, можно запустить go run *.go, который загрузит все файлы go в пакете и запустит main() .
  2. иди беги.
  3. идти строить.

Как запустить сценарий Linux?

Создайте файл, например, file.go, и его содержимое должно выглядеть так: ///path-to/bin/go run $0 $@; выйти $? package main func main() < println("Hello World!") >Затем запустите chmod +x file.go и затем вы можете выполнить его как ./file.go p1 p2 .

Можете ли вы работать в Linux?

По умолчанию go build создает исполняемый файл для текущей платформы и архитектуры. Например, если он создан в системе linux/386, исполняемый файл будет совместим с любой другой системой linux/386, даже если Go не установлен.

Как установить Golang в Linux?

Чтобы установить GoLang, нам сначала нужно его скачать. Затем распакуйте архив в локальный каталог. Затем мы добавляем PATH для бинарного файла Go….Установите Go для Linux

  1. Загрузите бинарный файл Go для Linux.
  2. Извлеките архив двоичных файлов GoLang.
  3. Установите PATH для Go.
  4. Проверьте установленную версию Go.

Как запустить скрипт в Ubuntu?

Простые шаги для запуска приложения Go в Ubuntu

  1. Напишите/клонируйте и создайте нашу программу Go. Сначала нам нужно подготовить нашу программу Go.
  2. Создайте файл системной службы. Далее создадим служебный файл для systemd.
  3. Запустите службу с помощью команды системной службы. Наконец, мы можем запускать или запускать службу приложений с помощью этой команды goapp start службы.

Как проверить версию моего go?

Получение версии Golang

  1. Загрузите и установите Go на свой компьютер.
  2. Убедитесь, что переменные окружения GOPATH и GOROOT установлены правильно.
  3. Откройте терминал и запустите версию go. Если вы получаете вывод с названием версии, Go установлен правильно.
  4. Создайте репозиторий в папке GOPATH/src.

Нужен ли Goroot?

В целом1 нет необходимости устанавливать переменную окружения $GOROOT при компиляции или использовании Go 1.0 или более поздней версии. На самом деле установка $GOROOT может привести к проблемам с отладкой, если на вашем компьютере установлено несколько версий Go. Вам все еще нужно установить $GOPATH .

Как узнать, есть ли у меня Gopath?

Команда go env GOPATH выводит действующий текущий GOPATH ; он печатает местоположение по умолчанию, если переменная среды не установлена. Дополнительные сведения о переменной среды GOPATH см. в разделе go help gopath .

Как просмотреть переменные среды в Golang?

Ниже приведен список функций, связанных с переменными среды, и их использования.

  1. Setenv() устанавливает значение значения среды.
  2. Getenv() получает переменную среды value, названную по ключу.
  3. Unsetenv() удаляет одно значение среды, названное ключом, если мы пытаемся получить это значение среды с помощью os.

Является ли Gopath устаревшим?

Он устарел. Это связано с тем, что вы все еще используете GOPATH и должны знать, как мы используем GOPATH сейчас и как мы использовали GOPATH для пакетов в прошлом.

Не можете найти посылку?

Дополнительные рекомендуемые действия. Добавьте $GOPATH/bin в $PATH по следующему пути: PATH="$GOPATH/bin:$PATH" Переместите main.go в подпапку $GOPATH/src , например $GOPATH/источник/тест. go install test теперь должен создать исполняемый файл в $GOPATH/bin, который можно вызвать, набрав test в терминале.

Где хранятся модули go?

Модули Go хранятся в каталоге $GOPATH/pkg/mod (каталог кеша модулей).

Как получить зависимости go?

Чтобы установить зависимости, используйте команду go get, которая также обновит файл go. файл мода автоматически. Поскольку в настоящее время пакет нигде в проекте не используется, он помечен как косвенный. Этот комментарий также может появиться в пакете косвенных зависимостей; то есть зависимость от другой зависимости.

Что такое модули Golang?

Модуль — это набор пакетов Go, хранящихся в дереве файлов с помощью go. файл мода в его корне. Идти.mod определяет путь модуля модуля, который также является путем импорта, используемым для корневого каталога, и его требования к зависимостям, которые являются другими модулями, необходимыми для успешной сборки.

Оглавление

Как запустить сценарий оболочки в Golang?

Чтобы сценарий оболочки можно было запускать напрямую, необходимо:

Как запустить файл .sh напрямую?

Метод GUI для запуска . ш-файл

  1. Выберите файл с помощью мыши.
  2. Щелкните файл правой кнопкой мыши.
  3. Выберите свойства:
  4. Перейдите на вкладку "Разрешения".
  5. Выберите Разрешить выполнение файла как программы:
  6. Теперь щелкните имя файла, и вам будет предложено. Выберите «Выполнить в терминале», и он будет выполнен в терминале.

Как выполнить команду в go?

Выполнение внешних команд в Go

Как запустить сценарий Linux?

Создайте файл, например, file.go, и его содержимое должно выглядеть так: ///path-to/bin/go run $0 $@; выйти $? package main func main() < println("Hello World!") >Затем запустите chmod +x file.go и затем вы можете выполнить его как ./file.go p1 p2 .

Что такое команда exec в Linux?

Команда exec в Linux используется для выполнения команды из самого bash. Эта команда не создает новый процесс, а просто заменяет bash командой, которую нужно выполнить. Если команда exec выполнена успешно, она не возвращается к вызывающему процессу.

Как выполнять команды оболочки, файлы скриптов в go?

Мы установили для STDOUT и STDERR значение os.Stdout, которое будет выдавать результат выполнения на терминал. Значение Args может сбивать с толку. Поскольку это фрагмент строки, мы предоставили соответствующий тип. Однако первое значение этого среза кажется странным.

Как запустить сценарий оболочки внутри кода Java?

Unix не умеет запускать скрипты внутри jar-файлов. Вы должны создать файл (существуют процедуры для создания временных файлов во время выполнения) с заданным содержимым, а затем запустить этот файл — см. Как запустить сценарий оболочки Unix из кода Java? для инструкций. Когда закончите, удалите его из файловой системы.

Как создать и запустить сценарий оболочки bash?

Теперь в этом «каталоге скриптов» создайте новый файл с именем hello.sh с помощью команды cat: Вставьте в него следующую строку, набрав ее в терминале: echo «Hello, World!» Нажмите Ctrl+D, чтобы сохранить текст в файл и выйти из команды cat.

Как я могу извлечь этот сценарий оболочки во время выполнения?

Выполнение сценария оболочки внутри файла jar. Как извлечь? Я разрабатываю Java-приложение только для Linux, и мне нужно выполнить в нем сценарий оболочки. Согласно тому, что я прочитал, единственный способ выполнить этот сценарий оболочки — извлечь его из файла jar и выполнить. Вопрос в том? Как я могу извлечь этот сценарий оболочки во время выполнения?

Как запустить оболочку?

Есть ли у Golang оболочка?

Gosh — это интерактивная оболочка Golang. Цель состоит в том, чтобы предоставить простую в использовании интерактивную среду выполнения.

Как открыть терминал в Golang?

Как запустить основной файл?

Вы можете создать программу Go в любом месте вашей системы. Типичная программа Go представляет собой обычный текстовый файл с расширением .go. Вы можете запустить эту программу с помощью команды go run hello.go, где hello.go — это файл программы Go в текущем каталоге.

Как выполнить команду оболочки в go?

Я хочу выполнить команду оболочки в Go и получить результат в виде строки в своей программе. Я видел версию Rosetta Code: но она не фиксирует фактический стандартный вывод или ошибку таким образом, к которому я могу получить программный доступ — они все еще выводятся в обычный стандартный вывод / стандартный вывод.

Как работает вывод в go exec?

Вывод запускает команду и возвращает ее стандартный вывод. В примере фиксируются выходные данные команды ls и распечатываются. Канал позволяет нам отправлять вывод одной команды другой. StdinPipe возвращает канал, который будет подключен к стандартному вводу команды при запуске команды.

Что делает Os/exec в Golang?

Пакет os/exec запускает внешние команды. Он обертывает os.StartProcess, чтобы упростить переназначение stdin и stdout, подключение ввода-вывода с помощью конвейеров и выполнение других настроек. Run запускает указанную команду и ожидает ее завершения.

Где я могу найти документацию по выполнению системных команд в go?

Примечание. Официальную документацию по выполнению системных команд можно найти в пакете exec: пакет os/exec. Вам понадобится Go версии 1.11+, установленный на вашем компьютере для разработки.

Этот пакет находится не в последней версии модуля.

Подробнее

Система модулей Go была представлена ​​в Go 1.11 и является официальным решением для управления зависимостями для Go.

Распространяемые лицензии накладывают минимальные ограничения на использование, изменение и распространение программного обеспечения.

Модули с помеченными версиями позволяют импортерам создавать более предсказуемые сборки.

Когда проект достигает основной версии v1, он считается стабильным.

Репозиторий

Документация ¶

Обзор ¶

Package exec запускает внешние команды. Он обертывает os.StartProcess, чтобы упростить переназначение stdin и stdout, подключение ввода-вывода с помощью каналов и выполнение других настроек.

В отличие от "системного" библиотечного вызова из C и других языков, пакет os/exec намеренно не вызывает системную оболочку и не расширяет какие-либо шаблоны подстановки или обрабатывает другие расширения, конвейеры или перенаправления, обычно выполняемые оболочками. Пакет ведет себя больше как семейство функций "exec" C. Чтобы расширить шаблоны glob, либо вызовите оболочку напрямую, стараясь избежать любого опасного ввода, либо используйте функцию Glob пакета path/filepath. Чтобы расширить переменные среды, используйте ExpandEnv пакета ОС.

Индекс ¶

  • func Command(имя строка, аргумент . строка) *Cmd
  • func CommandContext(ctx context.Context, строка имени, строка аргумента) *Cmd
  • func (c *Cmd) CombinedOutput() ([]байт, ошибка)
  • func (c *Cmd) Output() ([]byte, error)
  • func (c *Cmd) Ошибка Run()
  • func (c *Cmd) Ошибка Start()
  • func (c *Cmd) StderrPipe() (io.ReadCloser, ошибка)
  • func (c *Cmd) StdinPipe() (io.WriteCloser, ошибка)
  • func (c *Cmd) StdoutPipe() (io.ReadCloser, ошибка)
  • func (c *Cmd) String() строка
  • func (c *Cmd) Ошибка ожидания()
  • func (e *Error) Строка Error()
  • func (e *Error) Ошибка Unwrap()
  • func (e *ExitError) Строка Error()

Примеры ¶

Константы ¶

Этот раздел пуст.

Переменные ¶

ErrNotFound — это ошибка, возникающая, если при поиске по пути не удается найти исполняемый файл.

Функции ¶

функция LookPath ¶

LookPath ищет исполняемый именованный файл в каталогах, указанных в переменной среды PATH. Если файл содержит косую черту, он пробуется напрямую, а PATH не консультируется. Результатом может быть абсолютный путь или путь относительно текущего каталога.

Выполнить общий формат

Типы ¶

введите Cmd ¶

Cmd представляет внешнюю команду, которая готовится или выполняется.

Команду Cmd нельзя использовать повторно после вызова ее методов Run, Output или CombinedOutput.

команда func ¶

Command возвращает структуру Cmd для выполнения указанной программы с заданными аргументами.

Он устанавливает только путь и аргументы в возвращаемой структуре.

Если имя не содержит разделителей пути, Command использует LookPath для преобразования имени в полный путь, если это возможно. В противном случае он использует имя непосредственно как путь.

Возвращенное поле Args команды Cmd состоит из имени команды, за которым следуют элементы аргумента, поэтому аргумент не должен включать само имя команды. Например, Command("эхо", "привет"). Args[0] — это всегда имя, а не возможный разрешенный путь.

В Windows процессы получают всю командную строку в виде одной строки и выполняют собственный анализ. Команда объединяет и заключает аргументы в кавычки в строку командной строки с помощью алгоритма, совместимого с приложениями, использующими CommandLineToArgvW (что является наиболее распространенным способом). Заметными исключениями являются msiexec.exe и cmd.exe (и, следовательно, все пакетные файлы), которые имеют другой алгоритм раскатки. В этих или других подобных случаях вы можете сделать цитирование самостоятельно и указать полную командную строку в SysProcAttr.CmdLine, оставив Args пустым.

Выполнить общий формат

Выполнить общий формат

func CommandContext ¶ добавлено в версии go1.7

CommandContext похож на Command, но включает контекст.

Предоставленный контекст используется для уничтожения процесса (путем вызова os.Process.Kill), если контекст завершается до того, как команда завершится сама по себе.

Выполнить общий формат

func (*Cmd) Комбинированный вывод ¶

CombinedOutput запускает команду и возвращает объединенный стандартный вывод и стандартную ошибку.

Выполнить общий формат

func (*Cmd) Вывод ¶

Вывод запускает команду и возвращает ее стандартный вывод. Любая возвращаемая ошибка обычно имеет тип *ExitError. Если c.Stderr был равен нулю, вывод заполняет ExitError.Stderr.

Выполнить общий формат

func (*Cmd) Выполнить ¶

Выполнить запускает указанную команду и ожидает ее завершения.

Возвращенная ошибка равна нулю, если команда запускается, не имеет проблем с копированием stdin, stdout и stderr и завершается с нулевым статусом выхода.

Если команда запускается, но не завершается успешно, это ошибка типа *ExitError. Другие типы ошибок могут быть возвращены для других ситуаций.

Если вызывающая горутина заблокировала поток операционной системы с помощью runtime.LockOSThread и изменила какое-либо наследуемое состояние потока на уровне ОС (например, пространства имен Linux или Plan 9), новый процесс унаследует состояние потока вызывающей стороны.

Выполнить общий формат

func (*Cmd) Пуск ¶

Старт запускает указанную команду, но не ждет ее завершения.

Если Start завершается успешно, поле c.Process будет установлено.

Метод Wait вернет код выхода и освободит связанные ресурсы после завершения команды.

Выполнить общий формат

func (*Cmd) StderrPipe ¶

StderrPipe возвращает канал, который будет подключен к стандартной ошибке команды при ее запуске.

Wait закроет конвейер после того, как увидит выход из команды, поэтому большинству вызывающих абонентов не нужно закрывать канал самостоятельно. Таким образом, некорректно вызывать Wait до завершения всех операций чтения из канала. По той же причине некорректно использовать Run при использовании StderrPipe. См. пример StdoutPipe для идиоматического использования.

Выполнить общий формат

func (*Cmd) StdinPipe ¶

StdinPipe возвращает канал, который будет подключен к стандартному вводу команды при запуске команды. Труба будет закрыта автоматически после того, как Уэйт увидит команду exit. Вызывающему абоненту достаточно вызвать Close, чтобы принудительно закрыть канал. Например, если выполняемая команда не завершится, пока стандартный ввод не будет закрыт, вызывающая сторона должна закрыть канал.

Выполнить общий формат

func (*Cmd) StdoutPipe ¶

StdoutPipe возвращает канал, который будет подключен к стандартному выводу команды при ее запуске.

Wait закроет конвейер после того, как увидит выход из команды, поэтому большинству вызывающих абонентов не нужно закрывать канал самостоятельно. Таким образом, некорректно вызывать Wait до завершения всех операций чтения из канала. По той же причине некорректно вызывать Run при использовании StdoutPipe. См. пример идиоматического использования.

Выполнить общий формат

Строка

func (*Cmd) ¶ добавлена ​​в версии go1.13

String возвращает удобочитаемое описание c. Он предназначен только для отладки. В частности, он не подходит для использования в качестве входных данных для оболочки. Вывод String может различаться в разных версиях Go.

func (*Cmd) Подождите ¶

Wait ожидает завершения команды и завершения любого копирования в стандартный ввод или копирования из стандартного вывода или стандартного вывода.

Команда должна быть запущена кнопкой Пуск.

Возвращенная ошибка равна нулю, если команда запускается, не имеет проблем с копированием stdin, stdout и stderr и завершается с нулевым статусом выхода.

Если команда не запускается или не завершается успешно, это ошибка типа *ExitError. Другие типы ошибок могут быть возвращены для проблем с вводом-выводом.

Если какой-либо из c.Stdin, c.Stdout или c.Stderr не является файлом *os.File, функция Wait также ожидает завершения соответствующего цикла ввода-вывода, копирующего процесс или из него.

Wait освобождает все ресурсы, связанные с Cmd.

Ошибка типа ¶

LookPath возвращает ошибку, если ему не удается классифицировать файл как исполняемый.


В наших примерах мы будем запускать команду ls -lah, так как она выводит результат. В Windows нет ls, поэтому вы можете изменить это, например. список задач .

Выполнение команды

Если бы мы запускали ls -lah в оболочке, оболочка скопировала бы программные stdout и stderr в консоль, чтобы мы могли их увидеть.

Мы выполняем программу с помощью функции стандартной библиотеки Go, и по умолчанию stdout и stderr отбрасываются.

Выполнение команды и отображение вывода

Чтобы человек мог видеть выходные данные, мы можем соединить выходные данные ( cmd.Stdout и cmd.Stderr ) программы, которую мы выполняем, с os.Stdout и os.Stderr , которые являются выходными данными нашей программы:< /p>

cmd.Stdout и cmd.Stderr объявлены как интерфейс io.Writer, поэтому мы можем установить для них любой тип, реализующий метод Write(), например os.File или байты буфера в памяти.

Выполнение команды и запись вывода

Вышеприведенные примеры позволяют человеку видеть вывод, но иногда нам нужно зафиксировать вывод и проанализировать его:

За кулисами CombinedOutput

Преимущество Go в том, что это открытый исходный код, поэтому мы можем посмотреть, как реализована та или иная функциональность.

Другое преимущество заключается в том, что большая часть кода в стандартной библиотеке проста. Вот как реализован CombinedOutput:

Обратите внимание, что это почти так же просто, как во втором примере. Вместо того, чтобы устанавливать cmd.Stdout и cmd.Stderr на стандартный вывод, мы устанавливаем их на один буфер в памяти.

Захват stdout и stderr отдельно

Захват результатов, но также отображение прогресса

Было бы неплохо увидеть его прогресс на консоли, поскольку это происходит в дополнение к захвату stdout/stderr.

Ошибки, возникающие при чтении, обрабатываются очень тонко. Ошибка io.EOF означает, что мы все прочитали. Это не фактическая ошибка, поэтому мы превращаем io.EOF в nil .

Как предупреждает документация StdoutPipe, Wait закроет каналы, когда процесс завершится. Это может привести к потере части вывода, если мы не закончим его чтение.

Чтобы предотвратить это, мы используем синхронизацию.WaitGroup, чтобы гарантировать, что горутина, обрабатывающая os.Stdout, закончит чтение до того, как мы вызовем cmd.Wait .

Рекомендую ознакомиться с реализацией cmd.StdoutPipe . Вы будете удивлены, насколько он короткий.

Предыдущее решение работает, но copyAndCapture выглядит так, как будто мы заново реализуем io.Copy. Благодаря использованию интерфейсов в Go мы можем повторно использовать io.Copy .

Мы напишем структуру CapturingPassThroughWriter, реализующую интерфейс io.Writer. Он будет записывать все, что в него записывается, а также записывать в базовый io.Writer .

Оказалось, что стандартная библиотека Go реализует io.MultiWriter, более общую версию CapturingPassThroughWriter. Давайте воспользуемся этим:

Хорошо уметь писать код самому, но еще лучше хорошо знать стандартную библиотеку!

Запись на стандартный ввод программы

Нет библиотеки Go для сжатия bzip2 (в стандартной библиотеке доступна только распаковка).

Мы можем использовать bzip2 для сжатия следующим образом: * запись данных во временный файл * вызов bzip2 -c $ и получение его стандартного вывода

Мы также можем вызвать cmd.StdinPipe(), который вернет io.WriteCloser. Это сложнее, но дает больше контроля над написанием.

Изменение окружения исполняемой программы

  • os.Environ() возвращает []строку, где каждая строка имеет форму FOO=bar , где FOO – это имя переменной среды, а bar – значение
  • os.Getenv("FOO") возвращает значение переменной среды FOO .

Обычно вы не хотите создавать совершенно новую среду с нуля, а передаете модифицированную версию среды текущего процесса. Вот как добавить новую переменную:

Все становится сложнее, если вы хотите удалить среду или убедиться, что вы не устанавливаете одну и ту же переменную дважды. Пакет shurcooL/go/osutil предлагает более простой способ управления переменными среды.

Заранее проверьте, установлена ​​ли программа

Представьте, что вы написали программу, выполнение которой занимает много времени. В конце вы вызываете исполняемый файл foo для выполнения важной задачи.

Хорошо было бы определить отсутствие исполняемого файла foo в самом начале и выдать описательное сообщение об ошибке на раннем этапе.

Пакет exec определяется в пакете ОС. Это просто дополнительный пакет, позволяющий выполнять внешние команды с помощью Go.

В этом руководстве мы рассмотрим, как можно использовать пакет exec для запуска внешних команд.

Импорт пакета Exec

Чтобы использовать пакет exec, нам нужно его импортировать. Мы можем сделать это с помощью простой команды импорта:

После импорта вы можете выполнять команды, как мы увидим в этой статье.

Выполнение команд Golang

Давайте начнем с простого вызова команды, чтобы проиллюстрировать, как использовать пакет exec. Пример кода показан ниже:

package main
import (
"fmt"
"log"
"os/exec"
)
funcmain () <
cmd := исполнить . Команда ("dir")
вывод, ошибка := cmd. CombinedOutput()
if err != nil
log . Fatal (ошибка)
>
fmt. Printf ("Вывод: \n %s \n", строка (вывод))
>

В приведенном выше примере мы используем команду exec для получения списка файлов и каталогов с помощью команды dir.

Начнем с определения запускаемой команды с помощью метода Command. Синтаксис показан ниже:

Функция принимает команды для запуска в виде строкового аргумента. Затем он возвращает структуру команды для выполнения команды с предоставленными аргументами.

Следующий шаг — запустить команду с помощью метода CombinedOutput. Синтаксис метода показан ниже:

Метод запускает команду и возвращает объединенные stdout и stderr. Это возвращает фрагмент байта, который мы преобразуем в строку с помощью строкового метода.

После запуска приведенного выше кода он должен вернуть файлы и каталоги в текущем рабочем каталоге.

Установить текущий рабочий каталог

Мы можем определить текущий рабочий каталог, в котором будет выполняться команда, используя переменную cmd.Dir. Пример показан ниже:

package main
import (
"fmt"
"log"
"os/exec"
)
funcmain () <
cmd := исполнить . Команда ("каталог")
cmd. Dir = ".."
вывод, ошибка := cmd. CombinedOutput()
if err != nil
log . Fatal (ошибка)
>
fmt. Printf ("Вывод: \n %s \n", строка (вывод))
>

Захват Stdout и StdErr отдельно.

Вместо объединения Stdout и Stderr их можно захватывать по отдельности, как показано в приведенном ниже коде:

команда := исполнить . Команда ("каталог")
cmd. Dir = ".."
var stdout , stderr bytes. Буфер
cmd . Stderr = &stderr
cmd . стандартный вывод = & стандартный вывод
ошибка := cmd . Выполнить ()
if err != nil
log . Fatal ( err )
>
output , err := string ( stdout . Bytes ()), string ( stderr . Bytes ())

Укажите ОС

Вы также можете определить собственные команды для другой ОС, используя метод runtime.GOOS. Например:

Команды канала

Вы также можете направить вывод предыдущей команды, как показано в примере выше:

основной
импорт пакета (
"fmt"
"log"
"os/exec"
)

funcmain () <
first_cmd := `echo "Привет, мир" | wc -c`
cmd := exec . Команда ("bash", "-c", first_cmd)
вывод, ошибка := cmd. CombinedOutput()
if err != nil
log . Fatal (ошибка)
>
fmt. Printf("Вывод \n %s\n", строка (вывод))
>

Приведенная выше команда должна возвращать количество символов из команды echo.

Закрытие

В этом кратком руководстве показано, как начать работу с пакетом exec в Golang.

Об авторе

Джон Отиено

Меня зовут Джон, и я такой же гик, как и вы. Я увлечен всеми вещами компьютеров от аппаратного обеспечения, операционных систем до программирования. Моя мечта — поделиться своими знаниями с миром и помочь другим гикам. Следите за моим контентом, подписавшись на список рассылки LinuxHint

Читайте также: