Прочитать всю справочную страницу:
CPU
These are percentages of total CPU time.
us: Time spent running non-kernel code. (user time, including nice time)
sy: Time spent running kernel code. (system time)
id: Time spent idle. Prior to Linux 2.5.41, this includes IO-wait time.
wa: Time spent waiting for IO. Prior to Linux 2.5.41, included in idle.
st: Time stolen from a virtual machine. Prior to Linux 2.6.11, unknown.
Все это проценты от общего времени процессора.
Способов может быть множество, хотя все они требуют некоторой сложности для обработки случая переопределения.
В качестве одного -вкладыша, хотя и немного длинного, вы могли бы сделать это для одной итерации, т.е. для одного каталога "environments":
(r=Products; e=stage; (find -- "$r" -regextype posix-extended -maxdepth 2 \( -regex '^[^/]+(/[^/]+)?' -o ! -type d \) -print0; find -- "$r" -mindepth 1 -path "$r/*/$e/*" -print0) | tar --null --no-recursion -czf "$r-$e.tgz" -T- --transform=s'%^\(\([^/]\{1,\}/\)\{2\}\)[^/]\{1,\}/%\1%')
разбито для лучшего наблюдения:
(
r=Products; e=stage
(
find -- "$r" -regextype posix-extended -maxdepth 2 \( -regex '^[^/]+(/[^/]+)?' -o ! -type d \) -print0
find -- "$r" -mindepth 1 -path "$r/*/$e/*" -print0
) \
| tar --null --no-recursion -czf "$r-$e.tgz" -T- \
--transform=s'%^\(\([^/]\{1,\}/\)\{2\}\)[^/]\{1,\}/%\1%'
)
На что следует обратить внимание:
find
вы должны заменить -regextype posix-extended
только на -E
, а для BSD tar
вы должны заменить --no-recursion
только на -n
, а также--transform=s
(< -обратите внимание на окончательныйs
)на просто-s
Products
, и использует пользовательскую переменную $e
для имени каталога «environments» для архивирования, а $r
— это просто короткий -именованная вспомогательная переменная, содержащая имя Products
$r
и $e
, если вы запускаете ее из команды -строка $e
)Вы можете просто заключить этот фрагмент в цикл оболочки for e in dev prod stage; do...; done
и просто работать. (, возможно, удаляя крайние круглые скобки и окружая весь цикл for
).
Положительным моментом является то, что он довольно короткий и относительно простой.
Недостатком является то, что он всегда архивирует также все переопределенные файлы (, т.е. базовые ), хитрость в том, что двойные find
команды подают tar
с to -должны быть -переопределенными файлами в первую очередь, и, следовательно, во время извлечения они будут перезаписаны переопределяющими файлами (, т.е. файлами, специфичными для "окружения" ). Это приводит к тому, что больший архив занимает больше времени как при создании, так и при извлечении, и может быть нежелательным в зависимости от того, можно ли такими «накладными расходами» пренебречь или нет.
Этот конвейер, описанный в прозе,:
find
создает список не -конкретных файлов (и ведущих каталогов только в соответствии с вашим обновлением ), а вторая find
создает список всех сред, -специфичных только файлы find
сами по себе заключены в круглые скобки, так что оба их выхода подают канал в tar
последовательно tar
считывает такой канал, чтобы получить имена файлов, и помещает эти файлы в архив, а также--transform
-считывает их имена, удаляя компонент «среды» (, если он присутствует )из пути -имя каждого файла find
команды разделены вместо одной, и они выполняются одна за другой, так что не -определенные файлы создаются (для tar
использования )до специфические файлы среды -, что позволяет использовать трюк, описанный ранее Чтобы избежать накладных расходов, связанных с включением всегда всех файлов, нам нужны дополнительные сложности, чтобы действительно очистить переопределенные файлы. Один из способов может быть таким, как показано ниже:
# still a pipeline, but this time I won't even pretend it to be a one-liner
(
r=Products; e=stage; LC_ALL=C
find -- "$r" -regextype posix-extended \( -path "$r/*/$e/*" -o \( -regex '^([^/]+/){2}[^/]+' ! -type d \) -o -regex '^[^/]+(/[^/]+)?' \) -print0 \
| sed -zE '\%^(([^/]+/){2})([^/]+/)%s%%0/\3\1%;t;s%^%1//%' \
| sort -zt/ -k 3 -k 1,1n \
| sort -zut/ -k 3 \
| sed -zE 's%^[01]/(([^/]+/)|/)(([^/]+/?){2})%\3\2%' \
| tar --null --no-recursion -czf "$r-$e.tgz" -T- \
--transform=s'%^\(\([^/]\{1,\}/\)\{2\}\)[^/]\{1,\}/%\1%'
)
Несколько замечаний:
find
и tar
, применимо и здесь sed
для работы с нулевым -вводом-выводом с разделителями (параметром -z
), но вы можете легко заменить эти две sed
команды, например, на. потребуется while read...
цикл оболочки (Bash версии 3 или выше )или другой язык, в котором вы чувствуете себя уверенно,единственная рекомендация заключается в том, что инструмент, который вы используете, может обрабатывать ввод-вывод с нулевыми -разделителями (, например. GNU gawk
может это сделать ); см. ниже замену с использованием циклов Bash find
, так как я не полагаюсь на какое-либо подразумеваемое поведение изtar
sed
управляют списком имен, прокладывая путь для команд sort
sed
перемещает имя «окружения» в начало пути, также добавляя к нему префикс вспомогательного номера 0
, просто чтобы он сортировался перед файлами не -окружения, как я' m, добавляя к ним префикс 1
для сортировки sort
, делая все имена без имени «окружения» и все имеющие одинаковое количество полей, разделенных косой чертой -в начале, что важно для определения ключей sort
sort
применяет сортировку, основанную сначала на именах файлов, таким образом располагая одинаковые имена рядом друг с другом, а затем по числовому значению 0
или 1
, как отмечено ранее командой sed
, тем самым гарантируя, что любой файл, относящийся к "окружениям", если он присутствует, предшествует его неспецифичному -аналогу sort
объединяет (параметр-u
)в именах файлов, оставляя только первое из повторяющихся имен, которое из-за предыдущего переупорядочения всегда является файлом, специфичным для "окружения", если оно присутствует sed
отменяет то, что было сделано первым, тем самым изменяя имена файлов для tar
на архивные Если вам интересно изучить промежуточные части такого длинного конвейера, имейте в виду, что все они работают с нулевыми-именами с разделителями и, следовательно, плохо отображаются на экране. Вы можете подключить любой из промежуточных выходов (, т.е.убрав по крайней мереtar
)на любезность tr '\0' '\n'
, чтобы показать человекоподобный -вывод, просто помните, что имена файлов с новыми строками будут занимать две строки на экране.
Можно было бы сделать несколько улучшений, конечно же, сделав его полностью параметризованной функцией/скриптом или, например, автоматически обнаружив любое произвольное имя для каталогов «окружения», как показано ниже:
Внимание!:Обратите внимание на комментарии, так как интерактивная оболочка может их не принять.
(
export r=Products LC_ALL=C
cd -- "$r/.." || exit
# make arguments out of all directories lying at the second level of the hierarchy
set -- "$r"/*/*/
# then expand all such paths found, take their basenames only, uniquify them, and pass them along xargs down to a Bash pipeline the same as above
printf %s\\0 "${@#*/*/}" \
| sort -zu \
| xargs -0I{} sh -c '
e="${1%/}"
echo --- "$e" ---
find -- "$r" -regextype posix-extended \( -path "$r/*/$e/*" -o \( -regex '\''^([^/]+/){2}[^/]+'\'' ! -type d \) -o -regex '\''^[^/]+(/[^/]+)?'\'' \) -print0 \
| sed -zE '\''\%^(([^/]+/){2})([^/]+/)%s%%0/\3\1%;t;s%^%1//%'\'' \
| sort -zt/ -k 3 -k 1,1n \
| sort -zut/ -k 3 \
| sed -zE '\''s%^[01]/(([^/]+/)|/)(([^/]+/?){2})%\3\2%'\'' \
| tar --null --no-recursion -czf "$r-$e.tgz" -T- \
--transform=s'\''%^\(\([^/]\{1,\}/\)\{2\}\)[^/]\{1,\}/%\1%'\''
' packetizer {}
)
Пример замены первой команды sed
циклом Bash:
(IFS=/; while read -ra parts -d $'\0'; do
if [ "${#parts[@]}" -gt 3 ]; then
env="${parts[2]}"; unset parts[2]
printf 0/%s/%s\\0 "$env" "${parts[*]}"
else
printf 1//%s\\0 "${parts[*]}"
fi
done)
Для второй sed
команды:
(IFS=/; while read -ra parts -d $'\0'; do
printf %s "${parts[*]:2:2}" "/${parts[1]:+${parts[1]}/}" "${parts[*]:4}"
printf \\0
done)
Для обоих фрагментов требуются окружающие круглые скобки, чтобы их можно было -заменить соответствующими командами sed
в приведенном выше конвейере, и, конечно же, часть sh -c
после xargs
необходимо превратить в bash -c
. ].
Ограничения:
Рассматривайте это как доказательство концепции, настройте его под свои нужды.
Создание копии
cd
в родительский каталог Products
. Этот каталог Products
и все, что внутри, должно принадлежать одной файловой системе. Создайте временный каталог и воссоздайте Products
там:
mkdir -p tmp
cp -la Products/ tmp/
Изменение копии
Файлы в двух деревьях каталогов жестко связаны. Если вы измените их содержимое , вы измените исходные данные. Операции, которые изменяют информацию, хранящуюся в каталогах, безопасны, они не изменят исходные данные, если они выполняются в другом дереве. Это:
mv
), В вашем случае для каждого каталога с именем dev
на нужной глубине переместите его содержимое на один уровень вверх:
cd tmp/Products
dname=dev
find. -mindepth 2 -maxdepth 2 -type d -name "$dname" -exec sh -c 'cd "$1" && mv -f -- *../' sh {} \;
Примечания:
mv -- *../
склонен к argument list too long
, *
не соответствует точечным файлам. Затем удалите каталоги:
find. -mindepth 2 -maxdepth 2 -type d -exec rm -rf {} +
Обратите внимание, что это удаляет теперь пустые dev
и ненужные prod
, stage
; и любой другой каталог на этой глубине.
Архивирование копии
# still in tmp/Products because of the previous step
cd..
tar cvzf "products-$dname.tgz" Products
Удаление копии
# now in tmp because of the previous step
rm -rf Products
Повтор
Вернитесь в нужный каталог и начните заново, на этот раз с помощью dname=stage
; и так далее.
#!/bin/bash
dir=Products
[ -d "$dir" ] || exit 1
mkdir -p tmp
for dname in dev prod stage; do
(
cp -la "$dir" tmp/
cd "tmp/$dir"
[ "$?" -eq 0 ] || exit 1
find. -mindepth 2 -maxdepth 2 -type d -name "$dname" -exec sh -c 'cd "$1" && mv -f -- *../' sh {} \;
find. -mindepth 2 -maxdepth 2 -type d -exec rm -rf {} +
cd..
[ "$?" -eq 0 ] || exit 1
tar cvzf "${dir,,}-$dname.tgz" "$dir"
rm -rf "$dir" || exit 1
) || exit "$?"
done
Я сделал это немного более общим и работал с нетривиальными -именами файлов без фактического изменения исходных каталогов
Products
приводится в качестве аргумента. ключевые слова dev prod stage
жестко -закодированы внутри скрипта (, но могут быть легко изменены)
Примечание :это специальное расширение GNU --transform
и-print0
-z
запустить скрипт ./script Products
#!/bin/sh
# environment
subdirs="dev prod stage"
# script requires arguments
[ -n "$1" ] || exit 1
# remove trailing /
while [ ${i:-0} -le $# ]
do
i=$((i+1))
dir="$1"
while [ "${dir#"${dir%?}"}" = "/" ]
do
dir="${dir%/}"
done
set -- "$@" "$dir"
shift
done
# search string
for sub in $subdirs
do
[ -n "$search" ] && search="$search -o -name $sub" || search="( -name $sub"
done
search="$search )"
# GNU specific zero terminated handling for non-trivial directory names
excludes="$excludes $(find -L "$@" -type d $search -print0 | sed -z 's,[^/]*/,*/,g' | sort -z | uniq -z | xargs -0 printf '--exclude=%s\n')"
# for each argument
for dir in "$@"
do
# for each environment
[ -e "$dir" ] || continue
for sub in $subdirs
do
# exclude other subdirs
exclude=$(echo "$excludes" | grep -v "$sub")
# # exclude files that exist in subdir (at least stable against newlines and spaces in file names)
# include=$(echo "$excludes" | grep "$sub" | cut -d= -f2)
# [ -n "$include" ] && files=$(find $include -mindepth 1 -maxdepth 1 -print0 | tr '\n[[:space:]]' '?' | sed -z "s,/$sub/,/," | xargs -0 printf '--exclude=%s\n')
# exclude="$exclude $files"
# create tarball archive
archive="${dir##*/}-${sub}.tgz"
[ -f "$archive" ] && echo "WARNING: '$archive' is overwritten"
tar --transform "s,/$sub$,," --transform "s,/$sub/,/," $exclude -czhf "$archive" "$dir"
done
done
Вы можете заметить дубликаты внутри архива. tar
будет рекурсивно перемещаться по каталогам, при восстановлении более глубокие файлы будут перезаписывать файлы в родительском каталоге
Тем не менее, это требует дополнительной проверки согласованного поведения (не уверен в этом ). правильнее было бы исключить files1.json
+ files5.json
к сожалению -X
не работает с--null
Если вы не доверяете такому поведению или не хотите дублировать файлы в архивах, вы можете добавить исключение для простых имен файлов. раскомментируйте код выше tar
. символы новой строки и пробелы разрешены в именах файлов, но будут исключены с помощью подстановочного знака ?
в шаблоне исключения, который теоретически может исключить больше файлов, чем ожидалось (, если есть похожие файлы, соответствующие этому шаблону)
вы можете поместить echo
перед tar
, и вы увидите, что скрипт генерирует следующие команды
tar --transform 's,/dev$,,' --transform 's,/dev/,/,' --exclude=*/*/prod --exclude=*/*/stage -czhf Products-dev.tgz Products
tar --transform 's,/prod$,,' --transform 's,/prod/,/,' --exclude=*/*/dev --exclude=*/*/stage -czhf Products-prod.tgz Products
tar --transform 's,/stage$,,' --transform 's,/stage/,/,' --exclude=*/*/dev --exclude=*/*/prod -czhf Products-stage.tgz Products