Как защищать копию 5 самых последних файлов в локальный каталог

Тогда ответ заключается в том, что sudo имеет ошибку. Во-первых, обходной путь: /etc/sudoers.d/zabbix:

zabbix    ALL=(root) NOPASSWD:       /bin/env SHELL=/bin/sh /usr/local/bin/zabbix_raid_discovery

и теперь подкоманды, вызываемые из zabbix_raid_discovery, работают.

Патч, исправляющий это, будет в sudo 1.8.15. От сопровождающего, Тодда Миллера:

This is just a case of "it's always been like that".  There's not
really a good reason for it.  The diff below should make the behavior
match the documentation.

 - todd

diff -r adb927ad5e86 plugins/sudoers/env.c
--- a/plugins/sudoers/env.c     Tue Oct 06 09:33:27 2015 -0600
+++ b/plugins/sudoers/env.c     Tue Oct 06 10:04:03 2015 -0600
@@ -939,8 +939,6 @@
            CHECK_SETENV2("USERNAME", runas_pw->pw_name,
                ISSET(didvar, DID_USERNAME), true);
        } else {
-           if (!ISSET(didvar, DID_SHELL))
-               CHECK_SETENV2("SHELL", sudo_user.pw->pw_shell, false, true);
            /* We will set LOGNAME later in the def_set_logname case. */
            if (!def_set_logname) {
                if (!ISSET(didvar, DID_LOGNAME))
@@ -984,6 +982,8 @@
            if (!env_should_delete(*ep)) {
                if (strncmp(*ep, "SUDO_PS1=", 9) == 0)
                    ps1 = *ep + 5;
+               else if (strncmp(*ep, "SHELL=", 6) == 0)
+                   SET(didvar, DID_SHELL);
                else if (strncmp(*ep, "PATH=", 5) == 0)
                    SET(didvar, DID_PATH);
                else if (strncmp(*ep, "TERM=", 5) == 0)
@@ -1039,7 +1039,9 @@
     if (reset_home)
        CHECK_SETENV2("HOME", runas_pw->pw_dir, true, true);

-    /* Provide default values for $TERM and $PATH if they are not set. */
+    /* Provide default values for $SHELL, $TERM and $PATH if not set. */
+    if (!ISSET(didvar, DID_SHELL))
+       CHECK_SETENV2("SHELL", runas_pw->pw_shell, false, false);
     if (!ISSET(didvar, DID_TERM))
        CHECK_PUTENV("TERM=unknown", false, false);
     if (!ISSET(didvar, DID_PATH))
1
05.09.2018, 09:28
3 ответа

Только первый файл имеет абсолютный путь, необходимый scp.

${server}:${server_dir}/$(ssh ${server} "ls -t ${server_dir} | head -5")оценивается как

${server}:${server_dir}/iosTestOutput_20180831-175508-PDT.tgz
iosTestOutput_20180831-155546-PDT.tgz
iosTestOutput_20180831-142509-PDT.tgz
...

Для ясности я использовал символы возврата строки вместо пробелов.

По сути, вам нужно иметь цикл по сгенерированному списку, используя что-то, что выводит полный путь для каждого из пяти файлов.https://unix.stackexchange.com/a/240424/162359может быть хорошим началом.

(не проверено, просто грубый набросок )Что-то вроде:

for bkp in $(ssh ${server} "find ${absolute_path_remote_dir} -type f -exec stat -c '%X %n' {} \; | sort -nr | awk 'NR==1,NR==5 {print $2}'")
do
scp -r ${bkp} logs/ios
done

В rsync также может быть некоторая опция, которая поможет вам сделать то, что вы хотите, более элегантно.

2
27.01.2020, 23:42

Когда ты бежал:

scp -r ${server}:${server_dir}/$(ssh ${server} "ls -t ${server_dir} | head -5")

... первая (важная )вещь, которая произошла, заключалась в том, что ваша локальная оболочка начала интерпретировать подстановку команд здесь:

$(ssh ${server} "ls -t ${server_dir} | head -5")

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

  • temp file
  • a
  • b
  • c
  • d

ssh... ls -t | head -5даст вам:

a
b
c
d
temp file

... но подстановка команды удаляет новые строки из вывода, оставляя вам возвращаемую строку:

a b c d temp file

... которое теперь неотличимо от настоящих, оригинальных имен файлов.

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

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

server=server-name-here  ## replace with your values
server_dir=/tmp          ## replace with your values

files=($(ssh "$server" "zsh -c 'print -N -- ${server_dir}/*(om.[1,5])'" 2>/dev/null ) )
for f in ${files[1,5]}
do
  scp "${server}:${f}" logs/ios
done

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

  • файлы из каталога ${server _}
  • которые oупорядочены по mвремени модификации
  • и обычные файлы(.)
  • и только первые пять:[1,5]

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

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

Если вы хотите, вы можете тщательно создать строку имен удаленных файлов(${server}:${file1} ${server}:${file2}...)и вызвать scpтолько один раз. Возможно,:

scp ${server}:${(qq)^files[1,5]} logs/ios

... так как это указывает zsh добавить перед первыми пятью элементами массива строку (${server}, которая заменяется вашим реальным именем сервера, за которым следует двоеточие ). Любые имена файлов из массива заключаются в кавычки.

0
27.01.2020, 23:42

Как сказал hhoke1, у вас отсутствует абсолютный путь.

ls -t | head -5 | xargs readlink -f

Это должно дать вам абсолютный путь для scp, но похоже readlinkне может прочитать ввод из канала, поэтому я использовал xargs.

-1
27.01.2020, 23:42

Теги

Похожие вопросы