ssh-under-cron перестает работать в OS X 10.7 Lion

12

Я перешел с Snow Leopard на Lion, и мои задания cron, использующие ssh, перестали работать. Похоже, что ssh-agent больше не работает, как ожидалось.

Вот упрощенная версия моего сценария с названием «из-за-cron», который отлично работал под Snow Leopard:

#!/bin/bash
whoami # just to verify I'm running as myself, not root
ssh-agent # just to see what it outputs    
eval `ssh-agent`
ssh -vvv REMOTESERVER ls

При запуске из командной строки этот скрипт работает как положено.

При запуске из cron он не работает. Вывод ssh-agent выглядит нормально:

SSH_AUTH_SOCK=/tmp/ssh-QRxPUMRxbu/agent.17147; export SSH_AUTH_SOCK;
SSH_AGENT_PID=17148; export SSH_AGENT_PID;
echo Agent pid 17148;
Agent pid 17150

Но ssh -vvvвывод показывает, что он не работает, когда закрытый ключ должен быть прочитан:

debug1: Server accepts key: pkalg ssh-dss blen 818
debug2: input_userauth_pk_ok: fp ...
debug3: sign_and_send_pubkey: DSA ...
debug1: PEM_read_PrivateKey failed
debug1: read PEM private key done: type <unknown>
debug1: read_passphrase: can't open /dev/tty: Device not configured
debug2: no passphrase given, try next key

Другими словами, он ожидает от меня ввода ключевой фразы ~/.ssh/id_dsa, которая, конечно, не работает в заданиях cron.

Это все работало в Snow Leopard.

Обратите внимание , что у меня есть настройки связки ключей доступа , так что ssh, ssh-agentи ssh-addможет прочитать мою фразу для моего .ssh/id_dsaфайла - в результате я могу SSH из терминала приглашения без необходимости ввести свой пароль.

Нужно ли запускать эту проблему ssh-addв какой-то момент процесса входа в систему? Запуск его из стандартного приглашения bash не помогает работе cron (хотя, как ни странно, он запрашивает мою фразу-пароль ... которая, я думаю, не является необходимой из-за конфигурации Keychain Access).

ПРИМЕЧАНИЕ 1. - перед тем, как перенаправить меня, я знаю, что здесь есть похожий вопрос ( Mac OS X Lion и sshpass ), но он касается именно программы, sshpassкоторую я не использую (хотя я считаю, что на этот вопрос ответит и этот вопрос) ).

ПРИМЕЧАНИЕ 2. - Я понимаю, что SSH-ключи без пароля решают мою проблему; однако я бы предпочел не идти по этому пути.

Джон Харт
источник
2
Крон ушел. Смотрите здесь тег launchd для получения всевозможной помощи (сделайте ход - он обрабатывает порты, enviromnent и намного лучше, чем когда-либо делал cron) - я надеюсь, что у кого-то есть решение, но cron mojo здесь стареет наверняка ,
bmike
3
Крон все еще бежит во Льве ... но ты прав, я должен сделать ход. Тем не менее, более чем 10-строчный XML-файл, выполняющий работу одной строки crontab, довольно слабый. Может быть, через 10 лет они переключат plist-файлы на JSON, и будет много радости, а через 10 лет они вернутся в crontab, и серые бороды BSD будут смеяться. Полагаю, к тому времени я стану BSD-серой бородой ...
Джон Харт,
1
Просто переключился на launchd, работает брелок. Вызываемый скрипт вообще не должен взаимодействовать с ssh-agent - вы можете просто перейти сразу в команду ssh после hashbang. Если бы ваш комментарий был ответом, я бы его принял =)
Джон Харт
JSON, конечно, во многих случаях освещает XML, но все списки, которые были до этого, скорее всего, вызвали проблему. Мне просто кажется, что у нас есть унифицированная, эффективная, структурированная замена данных. cron и, конечно, служил нам хорошо целую вечность!
bmike
Я искал все выше и ниже дополнительные веб-ресурсы, но всегда возвращаюсь к этому посту. Конечно, кто-то может внести свой вклад в обсуждение? Я попытался использовать простой plist для запуска скрипта, но mailx не отправляет мои уведомления. Мне все еще нравится cron, и я все время использую его в Ubuntu. Я не хочу возвращаться к 10.6, но эта проблема убивает меня. Мне не нравится, когда меня заставляют использовать launchctl, и мне приходится изучать то, что мне кажется очень обширной средой для автоматизации сценариев оболочки. У кого-нибудь есть новые идеи?

Ответы:

10

Для тех, кто попадает на эту страницу, я понял, что должен опубликовать ответ:

Использование launchd вместо cron действительно решает проблему авторизации. Задания, запускаемые пользователем (которые запускаются только после входа в систему) правильно используют информацию агента SSH, которая была разблокирована через цепочку для ключей, как часть входа в систему (как часть стандартного управления ключами OS X, никакого другого программного обеспечения не требуется).

Чтобы свести к минимуму мое взаимодействие с launchd, я создал одно задание launchd, которое вызывает скрипт bash. Таким образом, я могу просто отредактировать скрипт, не имея дело с launchd.

Вот файл launchd:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>com.mycron.hourly</string>

  <key>ProgramArguments</key>
  <array>
    <string>/Users/john/bin/cron.hourly</string>
  </array>

  <key>Nice</key>
  <integer>1</integer>

  <key>StartInterval</key>
  <integer>3600</integer> <!-- start every X seconds -->

  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>

Я сохранил файл ~/Library/LaunchAgents/com.mycron.hourly.plist, а затем загрузил его:

launchctl load ~/Library/LaunchAgents/com.mycron.hourly.plist

После загрузки он будет запускаться сразу же, а затем каждые 60 минут.

Если вы выполните ту же процедуру, вы захотите изменить строку `ProgramArguments ', указав правильный путь к вашему сценарию.

Джон Харт
источник
2
Действительно, cron устарела, по крайней мере, в Lion. Престижность в поиске ответа - launchctl может быть трудно взломать изначально.
zwerdlds
7

Добавление следующего кода в ваш скрипт оболочки bash решит проблему:

declare -x SSH_AUTH_SOCK=$( find /tmp/launch-*/Listeners -user your_user -type s | head -1 )

Замените your_userна свое имя пользователя.

Этот код устанавливает правильное значение для SSH_AUTH_SOCKэтого информирует sshили scpо том, как общаться, ssh-agentкогда сценарий оболочки запускается из cron.

Вернер Антвейлер
источник
Это решило проблему, которая возникала у меня, когда scp не работал через launchd в сценарии оболочки, несмотря на то, что он нормально работал через обычную командную строку (iTerm или Terminal). Отличный совет.
TJ Luoma
Просто для протокола, на El Captain 10.11.2:zsh: no matches found: /tmp/launch-*/Listeners
Иван Балашов
1

Я ожидал бы, что усиленная безопасность, такая как песочница, и изменения для дальнейшего перемещения в 64-битную среду вызывают неожиданное горе.

Это не ответ, как таковой, но launchd получает всю любовь от яблока в эти дни.

Она не решает проблему cron, но более стабильна, и с ней может помочь больше людей.

bmike
источник
Очень хороший ответ там . Спасибо за публикацию.
bmike
1

Для тех, кто находит это сейчас, пытается выполнить эту работу в El Capitan и все еще не хочет превращать свою однострочную работу cron в скрипт launchd, ответ Вернера Антвайлера все еще работает, но путь изменился. Ниже работал для меня:

declare -x SSH_AUTH_SOCK=$(find /var/folders/*/*/*/*/agent.* -user your_user -type s | head -1)

ПРИМЕЧАНИЕ : не забудьте заменить your_user на ваше имя пользователя!

Это не позволило бы мне представить это как комментарий к его ответу, так как мне не хватает репутации, но я не хотел оставлять ее без обновления, поскольку это определенно помогло мне, наконец, настроить его.

Изменить: 30 марта 2016 г.

После некоторого тестирования я должен добавить, что это работает, только если агент использовался хотя бы один раз во время этого входа в систему. Для этого достаточно инициировать соединение ssh или запустить ssh-agent вручную. Скрипт запуска также можно использовать, если вы хотите, чтобы он запускался автоматически. Я создал файл startup.sh, который просто запускает ssh-agent, а затем с помощью редактора сценариев сохранил .app со следующим и добавил полученное приложение к своим элементам входа в систему:

do shell script "/path/to/startup.sh"
Petie
источник
Я решаю это прямо сейчас, и это не лучший способ. Очевидно, что запуск launchd - это путь, но для cron вы хотите установить свой ssh-ключ (с парольной фразой) в цепочке для ключей. Как только вы это сделаете, просто войдите в систему Mac, чтобы все настроить. Путь к сокету, который вы указали, хранится там, где вы запускаете ssh-agent вручную (и вводите вашу фразу-пароль вручную). На El Cap, после загрузки цепочки для ключей, найдите сокет через ls /private/tmp/com.apple.launchd.*/Listeners. Вам не нужно ничего делать, кроме входа в Mac.
Джо
launchd определенно является «официальным» способом сделать это, но для тех, кто хочет продолжать использовать cron, это действительно является жизнеспособным обходным путем. В моем тестировании простого входа в систему было недостаточно, чтобы ключ, сохраненный в цепочке ключей, функционировал через cron. Указанный вами путь определенно существует. Если он сгенерирован, как только вы вошли в систему и по-прежнему работает для cron, этого вполне достаточно, чтобы пропустить метод сценария запуска, который я перечислил. Конечно, стоит попробовать хотя бы - спасибо!
Пети
Я поместил это на место для процесса резервного копирования, и он работает корректно - при перезагрузках - уже более недели.
Джо