cat несколько файлов по одному ssh-соединению и получить возвращаемое значение для каждого

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

cat specific_file | ssh user@host -i /root/.ssh/id_rsa "cat >> result/specific_file"

Затем я просто проверял возвращаемое значение для каждой передачи (автоматически) и тем самым мог определить статус каждого файла. Мой вопрос: возможно ли это сделать через одно соединение ssh, но получить возвращаемое значение для каждого отдельного файла?

Заранее спасибо !

РЕДАКТИРОВАТЬ:

(b) Как вы можете видеть ниже, я генерирую команду для одного конкретного файла, а затем проверяю код возврата. Затем вызывается метод, содержащий эту часть программы, для различных типов данных.

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

sprintf(command,"/bin/cat /root/%s%s | /usr/bin/ssh [email protected] -i"
        " /root/.ssh/id_rsa \"/bin/cat >> result/%s%s\"", apmac,
        ending_str[source], apmac, ending_str[dest]);
rc = system(command);

if(rc != 0)
{
    sprintf(buffer, "[%i] - LOG ERROR from %s to %s CODE %i ", (int)time(0),
            ending_str[source], ending_str[dest], rc);
    sprintf(filename,"%s%s%s", LOCAL, apmac, ending_str[source]);
}
else
{
    sprintf(filename,"%s%s%s", LOCAL, apmac, ending_str[source]);
    remove(filename);
    sprintf(buffer, "[%i] - LOG process from %s to %s ok", (int)time(0),
            ending_str[source], ending_str[dest]);

    switch(source)
    {
    case PROBE_FILE:
        LOG_MASK_SET(globals->log_mask, LOG_MASK_PROB);
        break;
    case LIST_FILE:
        LOG_MASK_SET(globals->log_mask, LOG_MASK_LIST);
        break;
    case SCAN_FILE:
        LOG_MASK_SET(globals->log_mask, LOG_MASK_SCAN);
        break;
    default:
        /* Other cases not YET considered */
        break;
    }
}

ВТОРОЕ РЕДАКТИРОВАНИЕ:

Я запускаю этот код на маршрутизаторе как часть программы. Обратите внимание, что мне не разрешено добавлять в систему новые библиотеки или неосновные функции. Кроме того, клиент ssh в самой системе не поддерживает режим «-M».


person Torsten    schedule 01.12.2011    source источник


Ответы (3)


Изменить в ответ на добавленную информацию (и код):

К коду: я бы настоятельно рекомендовал написать сценарий/программу на принимающей стороне, чтобы общаться с отправляющим процессом по трубе ssh. Таким образом, у вас будет полная гибкость.

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

  • распаковывает каждый файл во временное место
  • пытается добавить операцию cat >> specific_file
  • выводит «запись результата» на стандартный вывод в качестве обратной связи с отправителем

Итак, вы бы сделали:

tar c file1 file2 file3 |
   ssh log-bot@remote /home/log-bot/handle_logappends.sh |
   while read resultcode filename
   do
       echo "$filename" resulted in code "resultcode"
   done

Чтобы обрабатывать отзывы на C/C++, вы должны посмотреть popen, что позволит вам читать потоковую обратную связь, как будто из файла, просто!

Пример такого скрипта handle_logappends.sh на принимающей стороне:

#!/bin/bash
set -e # bail on error

TEMPDIR="/tmp/.receiving_$RANDOM"
mkdir "$TEMPDIR"

trap "rm -rf '$TEMPDIR/'" INT ERR EXIT

tar x -v -C "$TEMPDIR/" | while read filename
do
    echo "unpacked file $filename" > /dev/stderr

    ## implement your file append logic here :)
    ## e.g. (?):
    cat "$TEMPDIR/$filename" >> "result/$filename"

    ## HERE COMES THE FEEDBACK PART: '<code> <filename>'
    echo "$?" "$filename"
done

Самое интересное здесь то, что, поскольку все находится в потоковом режиме, обратная связь для первого файла(ов) может поступать в то время, когда отправляющий tar все еще отправляет более поздние файлы на принимающий хост. Никаких ненужных задержек!

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

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

Надеюсь, это поможет!


Старый ответ:

Обычно вы прибегаете к хитроумным маленьким хитростям (не), например:

tar c file1 file2 file3 | ssh user@host -i /root/.ssh/id_rsa "tar x -C result/ -"

Добавьте подробный флаг, чтобы увидеть подробную информацию о ходе выполнения

tar c file1 file2 file3 | ssh user@host -i /root/.ssh/id_rsa "tar xvC result/ -"

Если хотите, можете заменить tar на cpio. Добавьте параметры, чтобы получить больше функциональности (например, -p для сохранения разрешений)


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

ssh user@host -i /root/.ssh/id_rsa  -MNf  # login, master, background without a command

for specific_file in file1 file2 file3
do
     cat "$specific_file" |
         ssh user@host -Mi /root/.ssh/id_rsa "cat >> 'result/$specific_file'"
     # check/use error code
done

person sehe    schedule 01.12.2011

Как насчет использования libssh2 вместо сценариев ssh и использования подсистемы sftp вместо создания собственной системы передачи файлов? в ракушке?

В libssh2/examples/sftp_append.c есть пример добавления одного файла, просто повторите это для нескольких файлов, которые вы хотите.

person ephemient    schedule 01.12.2011
comment
Привет, как я уже сказал, мне не разрешено добавлять библиотеки в систему. В качестве первого теста я понял это с помощью libssh2, но затем привязка его к программе действительно превысила лимит дискового пространства (я могу использовать только несколько КБ в системе). Поэтому я стараюсь использовать как можно больше предустановленных возможностей в системном объявлении. - person Torsten; 02.12.2011

если вы посмотрите на проблему с другой тактической точки зрения, вы можете скопировать все файлы из другого мастер-файла. Этот главный файл представляет собой сценарий оболочки, в который встроены документы с содержимым файлов. Затем выполните основной сценарий оболочки и просмотрите файлы — все в одном сеансе ssh. Это не красиво и не элегантно, но будет иметь успех.

person jouell    schedule 18.08.2017