Системные вызовы в go

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Всем привет!

Всеми нами любимый docker является абстракцией над операционной системой linux, kubernetes является абстракцией над docker, а openshift - это высокоуровневый дистрибутив kubernetes удобный для пользователя.

Технологии сейчас строятся на фундаменте из открытых программ, а самый очевидный путь их использования - системные вызовы из ваших собственных программ.

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

Для примера - в установщике openshift installer, данный интерфейс используется 450 раз. Стоит разобрать эту конструкцию, так как она позволяет сильно упростить многие процедуры за счет переиспользования существующих утилит, что бы не "создавать велосипеды" на ровном месте.

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

Для примера я сделал библиотеку, предоставляющую интерфейс к пакетному менеджеру arch linux - pacman.

Проверка зависимостей

Перед тем как использовать некоторую системную утилиту необходимо проверить её наличие в среде, в которой приложение будет производить системный вызов, сделать это можно с помощью команды exec.LookPath() , данная функция возвращает путь к необходимой утилите и ошибку если программа не найдена.

Эту функцию лучше вызывать на этапе инициализации или в начале main, что бы избежать непредвиденных ошибок в рантайме.

package main

import (
	"fmt"
	"os"
	"os/exec"
	"sync"
)

// Dependecy packages.
const (
	pacman  = `pacman`
)

func init() {
	_, err := exec.LookPath(pacman)
	if err != nil {
		fmt.Println("unable to find pacman in system")
		os.Exit(1)
	}
}

Параметры вызова

Структура exec.Cmd предоставляет большое количество параметров, что бы лучше с ними познакомиться лучше смотреть исходники. Так как статья имеет ознакомительных характер я пройдусь только по основным:

  • Path - это путь к вызываемой программе

  • Args - аргументы используемые при вызове

  • Env - переменные окружения

  • Dir - директория в которой будет исполняться программа

  • Stdin - пользовательский ввод (аналогичным образом с терминалом)

  • Stdout, Stderr - потоки стандартного вывода и ошибок программы

Вот пример вызова знакомой нам утилиты эхо:

package main

import (
	"fmt"
	"os"
	"os/exec"
)

func main() {
	cmd := exec.Command("echo", "hello exec!")
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Run()
	fmt.Println(err)
}

Данный код создаст вызов к программе эхо, перенаправит потоки вывода на стандартные утсановленные в системе и запустит процесс.

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

package main

import (
	"bytes"
	"fmt"
	"os/exec"
)

func main() {
	cmd := exec.Command("echo", "hello exec!")
	var b bytes.Buffer
	cmd.Stdout = &b
	cmd.Stderr = &b
	cmd.Run()
	fmt.Println(b.String())
}

Так же есть возможность перенаправить вывод программы сразу в несколько различных потоков, сделать это можно используя io.Multiwriter(), вот пример вывода одновременно в stdout и буфер в памяти:

package main

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
)

func main() {
	cmd := exec.Command("echo", "hello exec!")
	var b bytes.Buffer
	cmd.Stdout = io.MultiWriter(&b, os.Stdout)
	cmd.Run()
	fmt.Println(b.String())
}

Заключение

Интерфейсы для совершения системных вызовов есть во всех современных языках и позволяют переиспользовать функционал существующих утилит. Данной возможностью стоит пользоваться так как это позволяет экономить существенное количество времени. Наличие данных интерфейсов стоит учитывать как при написании серверного ПО, так и при создании клиентских приложений, например на electron или flutter.

Спасибо!

Источник: https://habr.com/ru/articles/737660/


Интересные статьи

Интересные статьи

Привет! Весна набирает силу, с каждым днем становится теплее, и мы решили появиться со статьей: давно не писали. Расскажем про внутреннее комьюнити системных аналитиков в Тинькофф — зачем оно нужно и ...
Привет, Хабр! Меня зовут Дмитрий Зайцев. Я руководитель ПК конференции DevOpsConf. А ещё CTO/CIO @flocktory.com. Помогаю компании делать платформу реферального маркетинга для половины магазинов рунета...
Мы привыкли к тому, что в российских командах разработки есть позиция системного аналитика.А есть ли системные аналитики за рубежом? Что входит в их обязанности? Востребованные ли это специалисты?В эт...
Устали от постоянных звонков через Zoom и соскучились по живому общению? Как известно, современные проблемы требуют современных решений. Американский стартап PORTL Hologram предлагает сде...
Для обучения в жизни нет лучшего времени, чем сегодня. На дворе 2019 год, и тема DevOps сейчас актуальна, как никогда. Говорят, что дни системных администраторов прошли, как миновала эпоха мей...