TL; DR: Использование echo pass | ssh -t -t user@host 'su -c "command"'
Это вызвало у меня головную боль и заняло некоторое время, чтобы понять. В другом месте есть подсказки об ответе, но я нигде не видел явно сформулированного ответа, поэтому потребовалось немного поиграться с ним, чтобы получить право.
Использование ssh
echo <password> | ssh -t -t <user>@<host> 'su -c "<command>"'
цитаты кажутся необходимыми. Если я пропустил одну или другую пару кавычек, я получил неправильные результаты для некоторых команд. Например, <…> ssh -t -t me@mypc su -c "ls -l /root/something_secure"
даст мне содержимое ls
домашнего каталога me
, игнорируя -l
и /root/something_secure
. Поэтому мне нужно было настроить кавычки следующим образом.
-t
- это то место, где находится магия для наших нужд, и да, вы должны поставить 2 из них. Выполнение echo pass | su -c command
может закончиться неудачей, поскольку su
не берет пароль от стандартного ввода. Поначалу выполнение echo pass | ssh <…> su -c command
кажется хорошей идеей, потому что su
необходимо получить ввод из ssh, а ssh получает его из стандартного ввода, но на самом деле su
получает его из "tty", а не из стандартного ввода. -t
говорит ssh подделать его, используя псевдо-tty, который отправляет стандартный ввод этому поддельному tty. Иногда ssh будет жаловаться и не захочет выделять псевдо-tty для вас, поэтому -t
дважды говорит ssh о необходимости заткнуться и сделать это в любом случае.
-t 'Принудительное выделение псевдо-tty,Это может использоваться для выполнения произвольных программ на экране на удаленной машине, что может быть очень полезно, например, при реализации сервисов меню. Несколько опций -t принудительно назначают tty, даже если ssh не имеет локального tty.
From man ssh
Пример:
echo MySecretPass | ssh -t -t me@mydevice 'su -c "chown me /some/file"'
Ssh не имеет параметра пароля. Если вы не настроили безопасный пароль без пароля, вам следует это сделать. Читайте здесь . В противном случае этот ответ предоставит вам пароль для su
, но вам все равно придется указать пароль для ssh для первоначального входа в систему через ssh.
Использование plink (ssh-like инструмент командной строки Putty для Windows)
echo <password> | plink -t -t -pw <password> <user>@<host> "su -c '<command>'"
Опять же, цитаты кажутся необходимыми. Если я их пропустил, результаты были неверными, как и в случае использования ssh
.
Пример:
echo RootPass | plink -t -t -pw MePass me@mydevice "su -c 'echo Rooty!> /root/rootiness'"
Причина аналогична рассмотренному выше разделу ssh.
Ваш любимый язык программирования
Если ваш любимый язык программирования поддерживает возможность выполнения команды оболочки и управления стандартным вводом / выводом для нее, тогда вместо передачи echo
вы можете вместо этоговыполните указанную выше команду ssh
или plink
(без эхо-сигнала по каналу), затем введите стандартный ввод пароля.
Так же для C #
Process process = new Process();
// If I remember correctly, I think UseShellExecute needs to be false to redirect std in/out
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true;
// You can use either ssh or plink; I'll use plink here
process.StartInfo.FileName = "<path to plink>\\plink.exe";
process.StartInfo.Arguments = "-t -t -l " + username + " -pw " + password + " " + hostname + " 'su -c \"MyCommand\"'";
process.StartInfo.CreateNoWindow = true;
process.OutputDataReceived += new DataReceivedEventHandler(FunctionCallbackYouMake);
process.ErrorDataReceived += new DataReceivedEventHandler(AnotherFunctionYouMake);
// I'm not actually sure if this next line is necessary, but I've been using it because of an example I used
process.SynchronizingObject = null;
process.Start();
И затем прочитайте поступающие данныечерез соединение ssh (plink) с помощью функции обратного вызова, которую вы делаете и предоставляете OutputDataReceived. Он имеет вид void f(object sending_process, DataReceivedEventArgs event)
Вы можете записывать данные в process.StandardInput
, включая пароль su
, например
process.StandardInput.Write(password);
process.StandardInput.Flush();
Я также делал нечто подобное в JavaТак что я знаю, что вы можете делать там почти то же самое, но это было так долго, что я не вспоминаю все детали, но это также включает в себя объект процесса и настройку обработчиков std in / out. Если у меня будет время, я могу включить некоторые из этих деталей.
Независимо от того, какой язык или метод вы используете, некоторые программы могут блокироваться, если они получают слишком много информации в своих выходных потоках или потоках ошибок, поэтому убедитесь, чтовы регистрируетесь как для стандартного вывода, так и для стандартной ошибки, даже если вас это не волнует, даже если все, что вы делаете, это считываете их данные и отбрасываете их.
Но не задавайте пароль жестко!
Поскольку это для программирования, обычно нет необходимости жестко кодировать пароли в скриптах. Вы можете, если вам абсолютно необходимо, но желательно использовать переменные вместо имени пользователя, пароля и имени хоста, чтобы вы были более защищены и ваш инструмент стал более гибким.
Например, у меня есть строка в WindowsCMD, который делает следующее
echo %password% | plink -t -t -pw %password% %username%@%ip% "su -c '<what I want to do goes here>'"
И имя пользователя, пароль и ip предоставляются в качестве аргументов в файл cmd. Также обратите внимание на пример C # выше, они являются переменными.