LINUX.ORG.RU
решено ФорумAdmin

Познаем магию sed (требуются знания и телепатия)

 , ,


0

1

Сейчас участвую в одном OpenSource проекте на добровольных началах. Хочу отловить один баг, связанный с sed.

Вопрос в том, почему одна конструкция как из bash-скрипта, так и из консоли отрабатывает нормально, а другая (со слов автора) — работает из консоли но не работает из скрипта. Автор не знатоке седа, говорю сразу.

Вариант, который работает из конфигурационного скрипта:

sed -i "\|$conf|d" /etc/$1/conf.d/config.conf

Вариант, который не работает (вместо переменной указан полный путь до конфига)

sed -i 's|Include '$HOMEDIR'\/'$user'\/conf\/mail\/'$domain'\/webmail\/mail.'$domain'.apache2.conf||g' /etc/apache2/conf.d/config.conf

Второй вариант работает только при запуске sed вручную.

Что можете подсказать?

Спасибо.

★★★★★

Ответ на: см. ОП насчет телепатии от Twissel

$HOMEDIR = /home, $user = admin, $domain = domain.tk

В скрипте понятно, а в консоле откуда всё это берётся?

$ echo "'s|Include '$HOMEDIR'\/'$user'\/conf\/mail\/'$domain'\/webmail\/mail.'$domain'.apache2.conf||g'"
's|Include ''\/''\/conf\/mail\/''\/webmail\/mail.''.apache2.conf||g'
Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)

А зачем это:

'\/'

слеш ведь в одиночных кавычках.

Если в начале скрипта указано «#!/bin/sh», то bash ставит переменную среды POSIXLY_CORRECT и это отключает gnu расширения sed'а.

mky ★★★★★
()
Ответ на: комментарий от Deleted

В консоле можно и вручную установить, суть не в этом :-)

Автор этого всего скрипта(скажу по секрету) вообще от Майков в стан OpenSource переметнулся :-D

Да и я по седу не спец от слова совсем.

Twissel ★★★★★
() автор топика
Ответ на: комментарий от Twissel

Да и я по седу не спец от слова совсем.

А я не уверен, что дело в sed. Дай выхлоп:

echo "'s|Include '$HOMEDIR'\/'$user'\/conf\/mail\/'$domain'\/webmail\/mail.'$domain'.apache2.conf||g'"

И в скрипт помести это echo.

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)

работает из консоли но не работает из скрипта.

А переменные окружения скрипт из libastral.so брать будет?

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

В cron переменные не сорцятся, в шеллы в неинтерактивном режиме — тоже.

(требуются знания и телепатия)

И телепатии не потребовалось.

mord0d ★★★★★
()
Ответ на: комментарий от mord0d

Да, я сейчас сижу смотрю там очень много «но» и дело не только в переменных окружения. С такой элементарщиной там все в порядке.

Видимо, автор где-то налажал при переписывании скрипта + к тому у меня нет доступа к его тестовому окружению, а у меня эта хрень не воспроизводится.

Я думал может где-то в «елочках» ошибка.

Twissel ★★★★★
() автор топика
Ответ на: комментарий от Twissel

автор где-то налажал при переписывании скрипта

Ну так пусть кажет весь скрипт. Проблема может быть и не в том куске, который ты тут кажешь.

mord0d ★★★★★
()
Ответ на: комментарий от mord0d

Э-эх, не хотел я раскрывать все карты, но OSS же!

https://github.com/kristankenney/hestiacp/blob/development/bin/v-delete-mail-...

Я чисто для себя хочу понять где там фигня. Тот чувак все равно фигашит по 16 часов в сутки и будет неоднократно переписывать это добро.

Twissel ★★★★★
() автор топика
Ответ на: комментарий от Twissel

Если я правильно понял, я бы написал так:

sed -i "s|Include $HOMEDIR/$user/conf/mail/$domain/webmail/mail.$domain.apache2.conf||g" /etc/apache2/conf.d/config.conf
mky ★★★★★
()
Ответ на: комментарий от Twissel

Если ситуация не воспроизводится, то сложно будет понять, где фигня.

И вариант с командой «d» в sed удаляет стоку, а с командой «s» заменяет строку на пустую, то есть со временем в конфиге будут накапливаться пустые строки.

mky ★★★★★
()

не хотел я раскрывать все карты

Если б я знал, что за жесть творится в коде, я бы не просил. ☺

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

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

mord0d ★★★★★
()
Ответ на: комментарий от mord0d

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

А вот это дельный совет, спасибо!

Но чел уже переписывает)

Twissel ★★★★★
() автор топика
Ответ на: комментарий от Twissel

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

  • s/something//
  • s|/path/to/file||
  • s@something else@@
  • s#dude@mail.tld##

Можно даже так:

  • s)lol))
  • s0cocaine00

И так далее.

В Perl можно делать s{something}{something else}, но это уже совсем другая история.

mord0d ★★★★★
()
Ответ на: комментарий от mord0d

Ну мне же что-то подсказывало (беглое знакомство с sed из темных углов моей памяти), что «елочка» там лишняя.

Twissel ★★★★★
() автор топика

Тред не читал.

…работает из консоли но не работает из скрипта…

В скрипте точно тот-же шел что в консоли?

Что можете подсказать?

Могу посоветовать переключение на какой-нибудь python как только [ba]sh начинает требовать плясок с бубном

MrClon ★★★★★
()
Ответ на: комментарий от MrClon

Спасибо уже более менее разобрались.

Пилим-тестим форк VestaCP с блэкджеком и девочками. Чувак до этого всю жизнь работал большей частью с инструментами офтопика — sed его не слушается попросту.

Все равно будем менять весь расклад, архитектуру.

Если есть время и интерес, а также английский на уровне, после пары полезных пуллреквестов «тимлид» может принять в команду Hestia

Twissel ★★★★★
() автор топика
Последнее исправление: Twissel (всего исправлений: 1)
Ответ на: комментарий от mord0d

работаю с нубами, шо паделать

# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line.
SPHINXOPTS    =
SPHINXBUILD   = sphinx-build
SOURCEDIR     = .
BUILDDIR      = _build

# Put it first so that "make" without argument is like "make help".
help:
        @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
        @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)



Кстати, если makefile выше запускать из cron, а не из интерактивного рута, там ведь надо в требухе

SPHINXOPTS    =
SPHINXBUILD   = sphinx-build
SOURCEDIR     = .
BUILDDIR      = _build
Прописывать полный путь до всего или делать так ?

Twissel ★★★★★
() автор топика
Ответ на: работаю с нубами, шо паделать от Twissel

если makefile выше запускать из cron

Оберни в мелкий скрипт, положи его куда-нибудь, и пускай из cron. У меня в тестовой билд-ферме устроено примерно (на самом деле гораздо сложнее, ибо приходится иметь дело с cmake, ninja и остальными) так:

#!/bin/sh

cd "/path/to/repos/${1}"
make clean || exit 1
{ git pull || svn up; } || exit 1
make -j2 || exit 1

А в crontab следующее:

// Hint: чтобы в скриптоте и crontab не нужно было прописывать полные пути до исполняшек, пропиши PATH в crontab.

0 0 * * * buildscript packagename

// Во FreeBSD все cronjobs репортятся по email искаропки, в GNU/Linux придётся лепить это дело на скотч из мозолей и соплей Столлмана.

Но если это ваш проект и вы используете git, то почему не воспользуетесь хуками?

Прописывать полный путь до всего или делать так ?

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

работаю с нубами, шо паделать

Одни могут, но не хотят, другие хотят, но не могут. Нубы со временем обучатся, а если человеку надоело, мотивации ему не отсыпешь.

mord0d ★★★★★
()
Ответ на: комментарий от mord0d

мотивации ему не отсыпешь.

+100500

Twissel ★★★★★
() автор топика
Ответ на: комментарий от mord0d

Оберни в мелкий скрипт, положи его куда-нибудь, и пускай из cron

Тимлид уже обернул, но, понятное дело из крона это не работает :-)

#!/bin/bash

# Change to docs directory
cd /var/www/docs.site.com/

# Set changed var
changed=0

# Run git remote
git remote update && git status -uno | grep -q 'Your branch is behind' && changed=1

if [ $changed = 1 ]; then
    git pull
    make html
    echo "Updated successfully"
else
    echo "Up-to-date"
fi

На выходе получается

Makefile:19: recipe for target 'html' failed

Twissel ★★★★★
() автор топика
Ответ на: комментарий от Twissel

Makefile:19: recipe for target ‘html’ failed

GNU/Make всегда был так информативен… Ты же понимаешь, что это совершенно бесполезно в решении твоей проблемы? ☺

Повысь verbosity, попробуй через which перебрать все используемые в скрипте бинари и через echo все используемые билд-системой переменные, которые она ожидает в environment.

git remote update && git status -uno | grep -q ‘Your branch is behind’ && changed=1

git remote update || exit 1; git status -uno | grep -q 'Your branch is behind' && changed=1

Иначе при фейле git remote update оно скипнет продолжение строки.

Я бы вообще переделал этот код как-нибудь так:

#!/bin/sh

cd /var/www/docs.site.com
if git remote update >/dev/null 2>&1; then
  if git status -uno | grep -q 'Your branch is behind'; then
    make clean
    git pull
    make html
    echo "Updated successfully"
  else
    echo "Up-to-date"
  fi
else
  echo "Failed"
fi
mord0d ★★★★★
()
Ответ на: комментарий от mord0d

Спасибо.

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

У меня нет доступа к тому серваку, так что буду разворачивать sphinx docs у себя и тестировать.

Twissel ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.