Truncate if necessary when moving file to filesystem with shorter NAME_MAX

В общем, пробовать простой подход с помощью ps - плохая идея. и grep , чтобы попытаться определить, запущен ли данный процесс.

Для этого было бы намного лучше использовать pgrep :

if pgrep "varnish" >/dev/null; then
  echo "Varnish in running"
else
  echo "Varnish is not running"
fi

См. Руководство для pgrep . В некоторых системах (вероятно, не в Linux) вы получаете флаг -q , который соответствует тому же флагу для grep , который избавляет от необходимости перенаправлять на / dev / null . Также есть флаг -f , который выполняет сопоставление в полной командной строке, а не только в имени процесса. Можно также ограничить сопоставление процессами, принадлежащими конкретному пользователю, используя -u .

Установка pgrep также дает вам доступ к pkill , который позволяет вам сигнализировать о процессах на основе их имен.

Кроме того, , если это сервисный демон , и если в вашей системе Unix есть способ запрашивать у нее информацию (например, работает она или нет), то это правильный способ его проверки.

В Linux у вас есть systemctl ( systemctl is-active --quiet varnish вернет 0, если он запущен, 3 в противном случае), в OpenBSD у вас есть rcctl и т. Д.


Теперь о вашем скрипте:

В вашем скрипте вы анализируете вывод ps ax .Этот вывод будет содержать имя самого скрипта, check_varnish_pro.sh , которое, очевидно, содержит строку varnish . Это дает вам ложное срабатывание. Вы бы это заметили, если бы во время тестирования запускали его без флага -q для grep .

#!/bin/bash
ps ax | grep '[v]arnish'

Запуск:

$ ./check_varnish_pro.sh
31004 p1  SN+     0:00.04 /bin/bash ./check_varnish_pro.sh

Другая проблема заключается в том, что вы пытаетесь «скрыть» процесс grep от обнаружения самим grep с помощью [v] в выкройке. Этот подход потерпит неудачу, если вы случайно запустите сценарий или командную строку в каталоге, в котором есть файл или каталог с именем varnish (в этом случае вы снова получите ложное срабатывание). Это связано с тем, что шаблон не заключен в кавычки, и оболочка будет выполнять с ним подстановку имени файла.

См .:

bash-4.4$ set -x
bash-4.4$ ps ax | grep [v]arnish
+ ps ax
+ grep '[v]arnish'
bash-4.4$ touch varnish
+ touch varnish
bash-4.4$ ps ax | grep [v]arnish
+ ps ax
+ grep varnish
91829 p2  SN+p    0:00.02 grep varnish

Наличие файла varnish заставит оболочку заменить [v] arnish на имя файла varnish , и вы получите нажмите на шаблон в таблице процессов (процесс grep ).

1
15.08.2017, 15:38
1 ответ

Следующая функция (проверенная в bash) попытается переместить свой первый параметр во второй параметр. Он ожидает (и проверяет) первый параметр как файл, а второй как каталог.

Локальная переменная «namemax» должна быть настроена на NAME_MAXвашей файловой системы.

moveshort() {
  local namemax=8

  # simple sanity checks
  [ "$#" -eq 2 ] || return 1
  local src=$1
  [ -e "$src" ] || return 2
  local dest=$2
  [ -d "$dest" ] || return 3

  local extension=${src##*.}
  local basename=${src%.*}
  # the base name has ($namemax - $extension - 1)
  # characters available to it (1 for the period)
  local maxbase=$((namemax - ${#extension} - 1))

  # shorten the name, if necessary
  basename=${basename:0:maxbase}

  # echo "Shortened name: ${basename}.${extension}"
  # find a new name, if necessary
  if [ -e "${dest}/${basename}.${extension}" ]
  then
    local index=1
    local lenindex=${#index}
    #local newbase=${basename:0:-lenindex}
    local newbase=${basename:0:maxbase - lenindex}
    # loop as long as a conflicting filename exists and
    # we're not out of space in the filename for the index
    while [ -e "${dest}/${newbase}${index}.${extension}" -a "${#index}" -lt "$maxbase" ]
    do
      index=$((index + 1))
      lenindex=${#index}
      newbase=${newbase:0:maxbase - lenindex}
    done
    if [ -e "${dest}/${newbase}${index}.${extension}" ]
    then
      echo "Failed to find a non-colliding new name for $src in $dest" >&2
      return 4
    fi
    basename=${newbase}${index}
    # echo "new name = ${basename}.${extension}"
  fi

  # perform the move
  mv -- "$src" "${dest}/${basename}.${extension}"
}

После проверки работоспособности функция сохраняет расширение и оставшееся базовое имя файла, а затем определяет, сколько символов доступно для использования в базовом имени файла.

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

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

Если у нас заканчивается место в имени файла, функция выводит ошибку и возвращается; в противном случае он пытается выполнить mv.

2
27.01.2020, 23:33

Теги

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