LINUX.ORG.RU

Проверить наличие файла на удалённом компе

 


0

1

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

Есть программа на СИ, работает на одном компьютере, нужно чтоб она проверяла наличие какого-либо файла на другом компе. Способ связи только SSH.

Как бы Вы это сделали?



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

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

...а всё сам нашёл. Ещё раз, спасибо.

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

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

совершенству безумия нет предела!

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

там внутри чистый bash скрипт генерирует и вызывается с линуксовыми утилитами...

Юниксвей же, всё правильно.

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

Всячески рекомендую posix_spawn, потому что он получает отдельный массив argv, имя файла наверняка переменное, а собирать командную строку из шелл-эскейпов - дело выполнимое, но неблагодарное. Потом кто-нибудь передаст имя файла как '$(rm -rf ~ >/dev/null 2>&1 &)myfile', и случится конфуз. Пример:

const char *hostname, *filename;
/* ... */
pid_t child;
const char **ssh_cmd = {"ssh", hostname, "sh", "-c", "test -r \"$1\"", "--", filename};
/* no shell injection possible here, filename may contain arbitrary characters */
if (posix_spawnp(&child, "ssh", NULL, NULL, ssh_cmd, environ)) assert(0 && "fork failed");
int status;
if (waitpid(child, &status, 0) != child) assert(0 && "Did you SIG_IGN SIGCHLD?");
if (!WEXITSTATUS(status)) { /* file is readable */ }

Да, безопасный код на C - это очень и очень много текста, мы любим его не за это. Но если hostname и filename захардкожены, system можно использовать.

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

Есть ещё проблема, когда запускаю ssh через system или popen, то valgrind сильно ругается...

at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x50BEE77: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
by 0x51767E5: lh_insert (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
by 0x5178DF9: int_err_set_item (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
by 0x51792BA: ERR_load_strings (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
by 0x51351AD: ERR_load_EC_strings (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
by 0x517A2BE: ERR_load_crypto_strings (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
by 0x11281E: ??? (in /usr/bin/ssh)
by 0x5D4382F: (below main) (libc-start.c:291)

LEAK SUMMARY:
definitely lost: 3,254 bytes in 8 blocks
indirectly lost: 5,898 bytes in 81 blocks
possibly lost: 0 bytes in 0 blocks
still reachable: 88,056 bytes in 2,736 blocks
suppressed: 0 bytes in 0 blocks

Когда делал ssl-сервер, то боролся с этими утечками примерно так...

ERR_free_strings();
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
ERR_remove_thread_state(NULL);

А в этом случае что делать?

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

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

Либо это баг в ssh. Выяснить это можно, если поставить отладочные символы для /usr/bin/ssh, взять исходники, из которых программа была собрана, внимательно вчитаться в места (не в libcrypto), где память выделяется, и ответить на вопрос: должна ли она быть освобождена до завершения работы программы?

Так или иначе, в Вашей программе этой утечки нет. Она в самой ssh.

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

Она в самой ssh

Ага, понял, спасибо. А вывод о том, что утечка происходит в самой ssh, Вы делаете на основании вот этой строки...?

by 0x11281E: ??? (in /usr/bin/ssh)

Дело в том, что в моей проге используется du, и то же есть ошибки...

1,664 bytes in 1 blocks are still reachable in loss record 2 of 2
at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x40D355: ??? (in /usr/bin/du)
by 0x402FD4: ??? (in /usr/bin/du)
by 0x4E5A82F: (below main) (libc-start.c:291)
 
LEAK SUMMARY:
definitely lost: 0 bytes in 0 blocks
indirectly lost: 0 bytes in 0 blocks
possibly lost: 0 bytes in 0 blocks
still reachable: 1,680 bytes in 2 blocks
suppressed: 0 bytes in 0 blocks

И подскажите пожалуйста, где почитать про валгринд.

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

Где почитать - сам нашёл.

Может быть это связано с...

«При анализе программ, которые используют подгружаемые модули может возникнуть ситуация, когда valgrind не может выдать информацию о коде, приведшем к выделению „потерянных“ блоков памяти. Это происходит из-за того, что в момент, когда valgrind собирает информацию о выделении и использовании памяти, модуль может быть уже выгружен, и valgrind не может найти отладочную информацию. Это приводит к тому, что при выводе отчета такие места будут отмечены знаками ???, что означает отсутствие отладочной информации.»

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

Сделай проще: подмонтируй при помощи sshfs нужную директорию. А там уж работай, как обычно это делаешь локально... Сам некоторые вещи именно так и делаю, чтобы не париться с тормознутостью system и т.п.

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

Зачем ты при помощи system вызываешь du, если это можно сделать средствами C (причем, всего лишь на страницу-другую кода!)?

anonymous
()

Способ связи только SSH.

SSH позволяет пробрасывать порты

Как бы Вы это сделали?

Стандартное клиент-серверное приложение. Только зачем именно си? Зачем придумывать сложности? Тут в самый раз какой-нить скриптец подойдет.

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

Всё верно. Во многих программах есть утечки. Иногда оставленные там намеренно, чтобы сэкономить время при завершении работы программы (всё равно операционная система возьмёт использованные ресурсы обратно себе).

Однажды я переделывал очень большую книгу из HTML в ePub при помощи Calibre. Тот выделил очень много памяти, залез в swap, но за 2 часа книгу переконвертировал. Я заметил готовый файл книги, потом заметил, что Calibre продолжает хрустеть жёстким диском, и подключился к нему при помощи strace. Там были сплошные вызовы munmap: calibre освобождал много маленьких блоков памяти по одному, каждый из которых нужно было достать из swap и пометить в куче как неиспользуемый. Если бы Calibre просто завершился, не делая эти free(), я бы сэкономил ещё минут 20, а ядро Linux просто бы пометило большой кусок swap как доступный для перезаписи.

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

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

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

Зачем ты при помощи system вызываешь du, если это можно сделать средствами C

Ну, наверно потому, что это уже сделано другими людьми, и вряд ли у меня получится сделать лучше.

Вся моя программа состоит из ~70 строк, зачем мне переписывать DU когда нужно всего-то загнать данные в файл...

char ducmd[128] = {0,};
snprintf(ducmd, 127, "du %s%s -a --time > /tmp/tempfile", pathsdir, syncdir);
...
system(ducmd);

Сделай проще: подмонтируй при помощи sshfs нужную директорию.

Спасибо, дельная мысль.

Всё верно. Во многих программах есть утечки. Иногда оставленные там намеренно, чтобы сэкономить время при завершении работы программы (всё равно операционная система возьмёт использованные ресурсы обратно себе).

Спасибо. То есть «вынуждать» ядро делать то, что по идее должен делать я, не считается «плохим тоном»?

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

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

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

Я другой аноним.

))))

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

Я не слишком продвинутый погромист, подскажите, как заставить DU выполняться в выделенном участке памяти?

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

как заставить DU выполняться в выделенном участке памяти?

чувствую я, что это не тот вопрос, на который тебе нужен ответ. но ответить я могу.

парсишь elf (с помощью libelf, или ручками, если жаждешь большего хардкора), выделяешь память при помощи mmap с флагом PROT_EXEC, копируешь в выделенную память исполняемый код из ранее переваренного эльфа, передаешь этому участку памяти выполнение. это ведь не то, чего ты хочешь?

du - это всего лишь небольшая программка написанная на си, исходники которой свободно доступны и распространяются в пакете coreutils

вот её сорцы ->https://git.savannah.gnu.org/gitweb/?p=coreutils.git;a=blob;f=src/du.c;h=ac44... - там есть все ответы, изучай.

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

это ведь не то, чего ты хочешь?

Для меня это хобби, поэтому хочу и буду пробовать. Большое спасибо.

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

Друг, настоящее хакерсто не о том. Многим кажется, что труЪ хакеры занимаются байтоебством, но это глупое заблуждение. Хакерсто, это когда ты берешь программу и делаешь её лучше, быстрее, безопаснее, либо просто заставляешь её работать иначе, так как тебе хочется. Но заниматься низкоуровневым трюкачеством для этого не обязательно. Мы живем в эпоху открытого кода, лучшие творения человечества доступны всем и бесплатно, главное уметь читать и понимать код. Со временем придет навык изменять и создавать. И только тогда ты сможешь постичь качественно новое ощущение радости созидания, которое недостижимо для большинства живущих. За деньги такое не купить.

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

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

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

snprintf(ducmd, 127, "du %s%s -a --time > /tmp/tempfile", pathsdir, syncdir);

pathsdir и syncdir - константы, которые много меньше 64 символов каждая и никогда не будут содержать специальных символов?

Спасибо. То есть «вынуждать» ядро делать то, что по идее должен делать я, не считается «плохим тоном»?

Только в том случае, если это отдельная программа (не библиотека, которой будут пользоваться другие программы, может быть, повторно), а выбор стоит между free(buffer); return 0; и return 0; из main(). То есть, если память выделяется один раз и нужна всё время работы программы. Такую (формально) утечку можно позволить себе оставить (но с комментарием, обосновывающим, почему здесь не освобождается память). Учитывая, что Valgrind говорит о том, что память является still reachable (т.е. в памяти на момент завершения есть указатель, но на нём не сделали free()), скорее всего, du имеет право так поступать (особенно если учесть, что du много вызывают в скриптах, и (теоретически) время на освобождение памяти может стать заметным в большом скрипте).

В противном случае это плохо, но люди всё равно это допускают, потому что лень или по ошибке. Будьте выше их. (Лично я изучил C++ только ради деструкторов.)

как заставить DU выполняться в выделенном участке памяти?

Он уже выполняется в отдельном участке памяти. У процессов (Вашего = родительского и du = дочернего) различные адресные пространства. Когда дочерний процесс du завершается (с утечками или без), ядро всё равно за ним подчищает, и родительская программа работает дальше.

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

pathsdir и syncdir

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

...

За пояснения спасибо.

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

Тогда либо проверяйте возвращаемое snprintf значение и падайте при превышении, либо выделите по меньшей мере (PATH_MAX + длина остальной строки) символов под команду.

Что будет, если оставить в конфиг-файле пробел в пути к папке или лишнюю кавычку?

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

Что будет, если оставить в конфиг-файле пробел в пути к папке или лишнюю кавычку?

В лог запишется ошибка и программа завершится.

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

Не сишные, а позиксовые. В самом синтаксисе C (не унаследованном от никсов stdlib) никаких скрщнй, как в моднявых язычках. И в правильных библиотеках для C — тоже. Чини свой стереотипы.

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