10 ответов:
на самом деле вы можете отключить переменную только для чтения. но я должен предупредить, что это хакерский метод. Добавление этого ответа, только как информации, а не как рекомендации. Используйте на свой страх и риск. Протестировано на ubuntu 13.04, bash 4.2.45.
этот метод включает в себя знание немного исходного кода bash и он наследуется от этой ответ.
$ readonly PI=3.14 $ unset PI -bash: unset: PI: cannot unset: readonly variable $ cat << EOF| sudo gdb attach $$ call unbind_variable("PI") detach EOF $ echo $PI $
я попробовал взломать gdb выше, потому что я хочу отключить TMOUT (чтобы отключить автоматический выход из системы), но на машине, у которой TMOUT установлен только для чтения, мне не разрешено использовать sudo. Но поскольку я владею процессом bash, мне не нужен sudo. Однако синтаксис не совсем работал с машиной, на которой я нахожусь.
это сработало, хотя (я положил его в мой .bashrc file):
# Disable the stupid auto-logout unset TMOUT > /dev/null 2>&1 if [ $? -ne 0 ]; then gdb <<EOF > /dev/null 2>&1 attach $$ call unbind_variable("TMOUT") detach quit EOF fi
согласно Man-странице:
unset [-fv] [name ...] ... Read-only variables may not be unset. ...Если вы еще не экспортировать переменную, вы можете использовать
exec "" "$@"чтобы перезапустить оболочку, конечно, вы потеряете все другие неэкспортированные переменные. Кажется, если вы начинаете новую оболочку безexec, оно теряет свое свойство только для чтения для этой оболочки.
команда readonly делает его окончательным и постоянным, пока процесс оболочки не завершится. Если вам нужно изменить переменную, не отмечайте ее только для чтения.
нет, не в текущей оболочке. Если вы хотите присвоить ему новое значение, вам придется раскошелиться на новую оболочку, где она будет иметь новое значение и не будет рассматриваться как
read only.$ { ( readonly pi=3.14; echo $pi ); pi=400; echo $pi; unset pi; echo [$pi]; } 3.14 400 []
использование GDB ужасно медленно. Вместо того, чтобы попробовать ctypes.sh . Он работает с помощью libffi для прямого вызова bash's unbind_variable () вместо этого, который каждый бит так же быстро, как с помощью любого другого bash builtin:
$ readonly PI=3.14 $ unset PI bash: unset: PI: cannot unset: readonly variable $ include ctypes.sh $ dlcall unbind_variable string:PI $ declare -p PI bash: declare: PI: not foundсначала вам нужно будет установить ctypes.sh:
$ git clone https://github.com/taviso/ctypes.sh.git $ cd ctypes.sh $ ./autogen.sh $ ./configure $ make $ sudo make installсм.https://github.com/taviso/ctypes.sh для полного описания и документов.
для любопытных, да это позволяет вызывать любую функцию в bash, или любую функцию в любой библиотеке связанный с bash или даже любой внешней динамически загружаемой библиотекой, если хотите. Bash теперь так же опасен, как и perl... ; -)
вы не можете, с ручной страницы
unset:для каждого имени удалите соответствующую переменную или функцию. Если параметры не заданы или задан параметр-v, то каждое имя ссылается на переменную оболочки. переменные только для чтения не могут быть отключены. если указано-f, то каждое имя ссылается на функцию оболочки, а определение функции удаляется. Каждая неназначенная переменная или функция удаляется из передаваемой среды к последующим командам. Если любой из RANDOM, SECONDS, LINENO, HISTCMD, FUNCNAME, GROUPS или DIRSTACK не задан, они теряют свои специальные свойства, даже если они впоследствии сбрасываются. Состояние выхода true, если имя не является только для чтения.
в частности wrt для переменной TMOUT. Другой вариант, если gdb недоступен, - скопировать bash в свой домашний каталог и исправить строку TMOUT в двоичном файле на что-то другое, например XMOUX. А затем запустите этот дополнительный слой оболочки, и вы не будете тайм-аут.
еще один способ "снять" переменную только для чтения в Bash-объявить эту переменную только для чтения в одноразовом контексте:
foo(){ declare -r PI=3.14; baz; } bar(){ local PI=3.14; baz; } baz(){ PI=3.1415927; echo PI=$PI; } foo;bash: PI: переменная только для чтения
bar;PI=3.1415927
хотя это не "сбивает" в пределах области видимости, что, вероятно, является намерением оригинального автора, это определенно устанавливает переменную только для чтения с точки зрения baz (), а затем делает ее чтение-запись из с точки зрения baz(), вам просто нужно написать свой скрипт с некоторой предусмотрительностью.
в zsh,
$ typeset +r PI(Да, я знаю, что вопрос говорит Баш. Но когда Вы Google для zsh, вы также получаете кучу вопросов bash.)
Comments