Как использовать awk вместо cmp для сохранения результатов сравнения с переменными

Просто чтобы добавить к хорошему ответу @JeffSchaller по конкретному вопросу:

how can I simulate it running from the cronjob to test?

Я могу поделиться работающей альтернативой запуску тестовых команд из cronjob.

Для начала стоит упомянуть одну тонкую деталь:

В традиционной среде, отличной от -SELinux, когда вы работаете как root (эффективный UID = 0 ), вы обычно можете переключиться на любой другой UID, который вам нравится, чтобы «получить» ограничения этого UID.

Это совсем не похоже на контексты SELinux :быть root (эффективным UID = 0 )обычно помещает вас в «неограниченный» контекст, но не позволяет автоматически свободно переключаться в другие контексты. Вам скорее нужно явное правило политики SELinux, которое предоставляет «неограниченному» контексту разрешение на выполнение этой конкретной операции «перехода». После того, как вы установили такое правило, команда runconуспешно поместит вас в этот контекст.

С практической точки зрения, для вашего случая вам, вероятно, понадобится политика SELinux, подобная простой:

allow unconfined_t crond_t:process transition;

(в предположении, что crond_t— это домен SELinux, под которым работает ваш демон crond)

Правило компиляции и установки полного модуля:

module unconfined-trans-crond 1.0;

require {
        type unconfined_t;
        type crond_t;
        class process transition;
}

allow unconfined_t crond_t:process transition;

После компиляции и установки этого модуля будет работать runcon, нацеленный на домен crond_tиз unconfined_t.Например:

# id
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
# runcon $(ps -q $(pgrep crond) -o context --no-header) sh
# id
uid=0(root) gid=0(root) groups=0(root) context=system_u:system_r:crond_t:s0
#

Также обратите внимание, что для использования runconвам не обязательно иметь UID 0, вам «только» нужно правильное правило политики, которое разрешает переход от вашего текущего контекста SELinux к целевому контексту SELinux.

На самом деле, полная команда, которую я обычно запускаю от имени пользователя root для проверки доступности демона (, например crond),:

runuser $(ps -q $(pgrep crond) -o user --no-header) -c 'runcon $(ps -q $(pgrep crond) -o context --no-header) /bin/bash'

, который дает оболочку, работающую с пользователем crond, а также с его контекстом SELinux.

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

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

ХТХ

0
15.04.2021, 02:47
2 ответа

Мне кажется, что вы описываете молчаливое сравнение двух файлов. Этот первый фрагмент поместит статус выхода из cmpв переменнуюduplicate(0=match, иначе возникнет проблема; см. man cmpдля получения подробной информации о значениях состояния выхода)

cmp -s prevFile newFile
duplicate=$?

Но я подозреваю, что затем вы собираетесь проверить значение $duplicateи выполнить над ним действие. В этом случае вы можете просто проверить выходное значение cmpнапрямую

if cmp -s prevFile newFile
then
    echo "Files match"
else
    echo "Files do not match (or one is missing, unreadable, etc.)"
fi

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

cmp -s "$prevFile" "$newFile"

А также подумайте, возможно ли, что $prevFileможет еще не существовать

Наконец, как насчет awk? Это не подходящий инструмент для этой работы, поэтому не используйте его здесь.

5
28.04.2021, 22:54

Для этого можно использовать awk. Просто нет особого смысла так делать. Существуют инструменты, специально предназначенные для сравнения файлов (diff, cmp, md5sumи т. д. ). С другой стороны, awk— это мощный язык сценариев, который можно использовать для решения произвольных задач. Таким образом, вы действительно можете повторно реализовать существующую функциональность этих инструментов в awk, но вы не получите от этого ничего, кроме более медленного и менее эффективного способа делать то, что эти другие инструменты делают лучше.

Например,эта awkпрограмма сообщит вам, идентичны ли два файла или отличаются:

$ cat comp.awk
#!/usr/bin/awk -f

BEGIN{
  differ=0
}
NR==FNR{
  a[FNR]=$0; 
  last=FNR; 
  next
}
{ 
  if(FNR>last || "x"$0"x" != "x"a[FNR]"x" ){
    differ=1
    exit;
  }
} 
END{
  if(FNR<last){
    differ=1
  }
  print differ
}

Таким образом, вы можете использовать это для сохранения сравнения в переменной:

duplicate=$(comp.awk prevFile newFile)

Переменная будет 0, если файлы одинаковые, и 1, если они разные. Но вы можете сделать то же самое, используя существующие инструменты, быстрее, эффективнее и, вероятно, надежнее :

.
duplicate=$(diff -q prevFile newFile)

Конечно, значение не будет простым 1или 0, это будет либо Files prevFile and newFile differ, либо пустая строка, но это не имеет практического значения. Предположительно, вы захотите использовать эту переменную в последующей тестовой операции, и вы можете сделать это отлично:

$ [[ -z $duplicate ]] && echo differ || echo same
differ

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

1
28.04.2021, 22:54

Теги

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