Sed заменяет каждую строку, а не одну строку

can you still recover if all three functions are marked readonly?

Да, обычно можно, но это не значит, что нужно.

Точно так же, как вы можете отменить установку переменных только для чтения , подключив отладчик и вызвав unbind_variable, как показано в ответе anishsane на этот вопрос , вы также можете отменить установку функций только для чтения, передав их имена в unbind_funcс помощью отладчика.

Это неразумный подход, когда они не предназначены только для чтения (, если это действительно когда-либо ). В этой ситуации следует использовать решение cuonglm , в котором используется то, как unsetобрабатывается в режиме POSIX.Это решение можно использовать в реальной жизни.

Поскольку нет фактической гарантии, что ваша оболочка будет вести себя разумно после того, как вы обойдете readonlyс помощью отладчика, я предлагаю избегать ее всякий раз, когда есть более разумная альтернатива, такая как выход и перезапуск вашей оболочки или замена вашей оболочки на новую с помощью exec.

С учетом сказанного, вот метод Анишсане , адаптированный для неустановленных функций вместо переменной:

cat <

Обратите внимание, что$$расширяется до идентификатора процесса оболочки, потому что никакая часть EOFв <не заключена в кавычки.

Я протестировал это на версии Bash 4.3.48 (1 )-на Ubuntu 16.04 LTS, и это сработало. Для этого вам понадобится gdb, хотя его можно адаптировать и для других отладчиков. Как прокомментировал anishsane , конвейер из catпредназначен для избежания взаимоблокировки, когда процесс, который передает входные данные в gdb, является тем, который gdbбыл остановлен. Я считаю, что он достигает этой цели, потому что в конвейере из двух или более команд Bash выполняет каждую команду в подоболочке. Но я не уверен, что это самый надежный способ. В конечном счете, однако, нет реальной гарантии, что это все равно работает, поскольку для Bash вполне разумно предполагать, что переменные и функции только для чтения не изменятся. На практике я предполагаю, что это работает практически всегда.

Чтобы использовать эту технику, как написано, вам нужно установить sudoи иметь возможность sudoполучить root права. Конечно, вы можете заменить его другим методом повышения привилегий -. В зависимости от того, какую ОС вы используете и как она настроена, вы можете вообще опустить sudoи запустить gdbот имени пользователя вместо пользователя root. Например, ядро ​​Linux сверится со значением /proc/sys/kernel/yama/ptrace_scope, которое вы можете установить с помощью sysctl и можете прочитать или (как root )записать, чтобы определить, какие процессы могут отлаживать другие процессы. Если значение равно 1, то отлаживать его может только непосредственный родительский процесс --или любой процесс, запущенный с правами root --.В большинстве последних систем GNU/Linux для него установлено значение 1, поэтому я включил sudo.

Это описание поведения ядра Linux несколько упрощено, так как разрешены другие значения ptrace_scopeи что отношение, требуемое 1, может быть скорректировано. Полную информацию см. всоответствующей документации .

-1
29.12.2019, 06:40
2 ответа

Теперь я чувствую себя дураком, это кавычки вызывают проблему в $RCLONESESSION в переменной $laststartline.

laststartline=$(grep -n '$RCLONESESSION'LastStart $scriptdirectory/$mountsconfig | awk -F: '{print $1}') ##OBTAIN LINE NUMBER FOR LAST START TIME FOR THIS SESSION

Необходимо изменить на:

laststartline=$(grep -n "$RCLONESESSION"LastStart $scriptdirectory/$mountsconfig | awk -F: '{print $1}') ##OBTAIN LINE NUMBER FOR LAST START TIME FOR THIS SESSION

Теперь все работает, спасибо за помощь @steeldriver.

1
28.01.2020, 05:08

Ответ на другой вопрос. Нет необходимости в том, чтобы grep находил номер строки, так как sed может искать эту строку сам.

sed -i '/'$RCLONESESSION'LastStart:/s/.*/'$RCLONESESSION'LastStart:'$time'/' $scriptdirectory/$mountsconfig

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

sed -i 's/\('$RCLONESESSION'LastStart:\).*/\1'$time'/' $scriptdirectory/$mountsconfig

(Если $RCLONSESSION не находится в начале строки, измените s/\(наs/^.*\()

1
28.01.2020, 05:08

Теги

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