LINUX.ORG.RU

Использование в своих программах других программ

 ,


2

3

Здравствуйте.

Скажите, если я в своей программе (СИ, линукс) вызываю другие программы (wget или df или curl или ifconfig и т.д.), это ведь стандартная практика. Или я ошибаюсь?



Последнее исправление: stD (всего исправлений: 1)

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

yoghurt ★★★★★
()

Это в общем случае нормальная практика. Но зависит от нюансов. Например, если твоя программа не консольная, а гуёвая, надо как-то транслировать вывод дочернего процесса, дабы пользователь не думал, чтобы у него всё зависло. Ну и обрабатывать возможные ошибки надо.

hobbit ★★★★★
()
Ответ на: комментарий от hobbit

Речь о консольных программах, гуёвые я писать не умею.

stD
() автор топика
Ответ на: комментарий от Harald

Да. Это юниксвей и это хорошо

Вопрос мой собственно и возник из этого «термина» (юниксвей), прочитал и не понял, что имеется в виду: использование других программ в своих или конвейеров типа - iconv -f cp1251 -t utf8 < album_cp1251.cue > album_utf8.cue

stD
() автор топика

ИМХО правильнее использовать соответствующие библиотеки (например, libcurl).

1) Это более производительно (и всё равно Unix way - ты же не изобретаешь свой велосипед, а используешь готовый).

2) Нет кучи проблем с экранированием, обработки граничных случаев формата вывода этих утилит и т. д. Просто представь, что ты собираешься парсить URL из вывода wget (ведь он может отличаться от переданного из-за HTTP перенаправлений и вдруг тебе нужно именно итоговый URL зачем-то), а он содержит всякие последовательности, которые можно трактовать как другие сообщения wget. И такое бывает почти с каждой утилитой.

KivApple ★★★★★
()

тебе тут пытаются сказать, что это было нормально раньше, когда доступ к нормальным языкам и компиляторам был ограничен. тогда bash был хорошим средством для макрамэ из кирпичиков coreutils.

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

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

рекомендую поглядеть также на Plan9 и Inferno и почитать Д. Ричи

anonymous
()
Ответ на: комментарий от stD

И то, и другое. Преимущества в быстроте достижения результата и изоляции процессов друг от друга, меньше вероятность ошибок. Можно линковаться с библиотекой, исправлять баги в процессе отладки, а можно вызвать готовую программу, в которой эти баги 100 лет назад уже исправили

Harald ★★★★★
()
Ответ на: комментарий от hobbit

Спасибо всем, я всё уяснил.

stD
() автор топика

Не надо так делать. Для этого есть баш, а не сишка.

RazrFalcon ★★★★★
()

Скорее всего это значит, что твоё решение плохо спроектировано.

Если тебе нужно вызывать другую утилиту, это значит, либо что твою прогу можно заменить шелл скриптом и нет смысла писать её на C. Либо твоя утилита должна быть входом или выходом для утилиты которую ты используешь.

Так стоит делать только если времени мало, а сделать надо вчера и дёшево. Т.е. о5 же - не на C, в общем случае или если надо очень быстро вкорячить какой то функционал в имеющийся код на C а времени разбираться нет. Исключением является использование утилит, которые рассчитаны на такой вариант использования - например, lsp сервер или gdb mi.

pon4ik ★★★★★
()
Ответ на: комментарий от pon4ik

Скорее всего это значит, что твоё решение плохо спроектировано

Допустим мне нужно узнать кол-во свободного места на диске, использование df через popen будет «плохим тоном»?

stD
() автор топика
Ответ на: комментарий от anonymous

#include <sys/statvfs.h>

и вообще.. если так тяжело кодить на C, почему бы не глянуть на что-то по-современнее? на тот же Go, к примеру, или Rust?

anonymous
()

В целом, это нормально, но весь запуск дочерних процессов и взаимодействие с ними в линуксе сломаны и не вылечены до сих пор, из-за чего писать сложные программы с многопоточностью, библиотеками и дочерними процессами крайне сложно. Некоторые подробности есть тут: https://www.macieira.org/blog/2012/07/forkfd-part-1-launching-processes-on-unix/ (и по ссылкам от туда).

vzzo ★★★
()
Ответ на: комментарий от stD

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

Максимум такое решение годно как заглушка на скорую руку.

pon4ik ★★★★★
()

Кстати, моё заявление о признаке плохой архитектуры правда только для posix совместимых и win32. Есть платформы, где это приветсвуется и всячески поддерживается.

pon4ik ★★★★★
()

это ведь стандартная практика.

Нет, в C стандартная практика это использовать API для языка C. Что ещё хуже, в общем случае запуск и обработку внешнего процесса весьма сложно сделать полностью правильно, товарищ vzzo даёт полезные ссылки. Максимум это запускать свои же самописные хелперы, которые специально написаны для запуска из основной программы и будут поставляться вместе с основной программой в одном пакете и исходный код которых контролируется.

d_a ★★★★★
()
Последнее исправление: d_a (всего исправлений: 1)
Ответ на: комментарий от stD

прочитал и не понял, что имеется в виду: использование других программ в своих или конвейеров типа - iconv -f cp1251 -t utf8 < album_cp1251.cue > album_utf8.cue

Второе. Юниксвей это определённый ряд рекомендаций к CLI твоей программы.

d_a ★★★★★
()
Последнее исправление: d_a (всего исправлений: 1)

Всё зависит от случая, у меня вот сейчас хочешь не хочешь, а нужно вызывать через popen проприетарные консольные программы и следить за их работой (выводом) прибивать в случае чего и перезапускать с другими параметрами. В любом случае если это разовые нечастые вызовы или если нет возможности использовать библиотеки делающие тоже самое или если это наколенная, но полезная поделка которая вызывается в системе где заведомо есть нужная программа для вызова то почему бы и нет, Си универсальный язык и имеет механизмы для работы с внешними программами так что не слушай хейтеров, но! во всём должна быть мера, порой сложно обработать на С что-то, но можно встроить lua например если очень захочется и это нормально. Да в целом всё нормально лишь одно, system использовать часто не гоже, так как даже минимум что нужно, а именно получения нормального вывода не получишь. И в целом если есть возможность можно использовать простой bash скрипт или make сценарий. Касательно например wget, если у тебя реально 1 день и не времени изучать можно сделать заглушку на нём, но как появиться время переписать на libcurl, со всем остальным также. Использование внешних программ иногда удобно для прототипирования например.

Deleted
()
Ответ на: комментарий от d_a

Ну самый яркий пример который я видел это формы os/400. Там так построенно api (в том числе и расширения posix вокруг system()), что вызов другой программы практически ничем не отличается от вызова библиотечных функций нативного api. А нативный пользовательский интерфейс позволяет обмениваться данными формам из разных [под]программ. Т.е. там любая программа может быть использованна как подпрограмма, если реализована согласно гайдлайнам системы.

Второй пример, который однако в риал лайф особо никто не пользует - это возможности win32 pe формата. Там он по сути является чем то сильно похожим на эльфовский so, но ещё и с точкой входа для запуска.

Ещё можно сюда притянуть com/corba, но это уже не совсем в тему, хотя если сконцентрироваться на activeX то по сути всё тоже около того крутится.

pon4ik ★★★★★
()
Ответ на: комментарий от pon4ik

У меня под win32 ресурсоемкий сервер (ffmpeg в режиме трансляции RTP) запускается из корявой гуйни на C, так вот его вантуз иногда убивает нафиг, если память переполнена/аппаратный декодер зависает, а я это ловлю и обрабатываю. Напрямую через libav падает основное приложение, а свой хелпер лень поддерживать...

ЧЯДНТ?

timdorohin ★★★★
()
Ответ на: комментарий от timdorohin

Не используешь seh видимо, тем более под виндой даже потоки можно терминэйтить почти невозбранно. Я уже давненько не трудился под оффтопик.

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

pon4ik ★★★★★
()
Ответ на: комментарий от RazrFalcon

Там в статье автор пишет, что QProcess с текущими ядром и glibc нельзя реализовать без состояния гонки. Хоть и маловероятно, но это может привести к краху программы.

anonymous
()
Ответ на: комментарий от vzzo

из-за чего писать сложные программы с многопоточностью, библиотеками и дочерними процессами крайне сложно

и с тех пор ничего не изменилось ?

x905 ★★★★★
()

ИМХО, нет

Огромный плюс Линуксового софта, что почти весь функционал реализован в виде набора библиотек, а стандартные тулзы это набор вызовов к этим либам, за wget не скажу, но curl - libcurl, df - системные вызовы, и тд. Используя сторонние приложения, ты можешь наткнуться на ситуация дистрозависимости, например тот же ifconfig ныне устаревший и заменен на ip. Иными словами если строить на «дефолтных» библиотеках и системных вызовах продиктованных Posix и пр. стандартах, ты обеспечишь совместимость, переносимость и долгую жизнь своим тулзам. Очень рекомедую почитать «The linux programming interface» и «21st Century C: C Tips from the New School»

sparks ★★★★
()
Ответ на: комментарий от vzzo

Возвращаясь к вопросу...

Если я из своей программы запускаю (через popen) вот такой скрипт:

#!/bin/sh
ps aux | awk '{s += $3} END {print s}'

free | grep Память | awk ' {print $3}'

telnet localhost 7634 | awk -F'|' '{print $4}'

sensors -A | grep fan1 | awk '{print $2}'

sensors -A | grep fan2 | awk '{print $2}'

df -h | grep /dev/sda1 | awk '{print $3 "  " $4}'

df -h | grep /dev/sdb2 | awk '{print $3 "  " $4}'

exit 0

Сама программа представляет из себя телеграмбот (работающий на домашнем сервере), таким образом я смотрю текущее состояние.

stD
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.