NullPointerException
s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException
. Они наиболее распространены, но другие способы перечислены на странице NullPointerException
javadoc.
Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException
, be:
public class Example {
public static void main(String[] args) {
Object obj = null;
obj.hashCode();
}
}
В первой строке внутри main
я явно устанавливаю ссылку Object
obj
равной null
. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException
, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.
(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)
Ваша проблема: вся ваша команда помещается в одинарные кавычки - очевидно, чтобы выражения bash были расширены на сервере, а не локально.
Но это также относится к вашему $1
.
Простое решение: «Переключить» цитату, обернув вашу локальную переменную в одинарные кавычки.
ssh root@192.168.0.1 'echo "#date added $(date +%m/%d/%Y)" >> /var/named/chroot/etc/named.conf; echo "zone \"'$1'\" { type master; file \"/etc/zone/dummy-block\"; };" >> /var/named/chroot/etc/named.conf'
NB: \"$1\"
→ \"'$1'\"
.
ПРИМЕЧАНИЕ. решение является простым исправлением для однострочного интерфейса, как указано в вышеприведенном вопросе. Если есть хоть малейшая вероятность, что этот скрипт выполняется другими людьми или он может обрабатывать внешний вывод любого типа, пожалуйста, посмотрите на решение Charles Duffy .
Во-первых, вы не хотите, чтобы это были два отдельно перенаправленных оператора echo
- это неэффективно и означает, что строки могут оказаться не рядом друг с другом, если что-то еще добавляет в одно и то же время .
Во-вторых, и что еще более важно, вы не хотите, чтобы удаленная команда запускалась как нечто, что могло бы избежать его кавычек и запускать на вашем сервере произвольные команды (подумайте, $1
- '$(rm -rf /)'.spammer.com
).
Вместо этого рассмотрим:
#!/bin/bash
# ^ above is mandatory, since we use features not found in #!/bin/sh
printf -v new_contents \
'# date added %s\nzone "%s" { type master; file "/etc/zone/dummy-block"; };\n' \
"$(date +%m/%d/%Y)" \
"$1"
printf -v remote_command \
'echo %q >>/var/named/chroot/etc/named.conf' \
"$new_contents"
ssh root@192.168.0.1 bash <<<"$remote_command"
printf %q
выводит данные таким образом, что прохождение оценки в другой оболочке bash будет оценивать это содержимое обратно к себе. Таким образом, удаленная оболочка будет гарантирована (до тех пор, пока это bash) правильно интерпретировать контент , даже если контент пытается избежать его окружающих кавычек .
$1
является'"$(rm -rf /)"'
(где эти внешние кавычки являются буквальным текстом, а не синтаксисом). Я предпочел бы, чтобы злоумышленник помещал мусор в named.conf, а не позволял им запускать произвольные команды на моем сервере имен. – Charles Duffy 16 September 2014 в 21:18