citando nas construções do tipo ssh $ host $ foo e ssh $ host "sudo su user -c $ foo"
<p>freqüentemente acabo emitindo comandos complexos sobre ssh; esses comandos envolvem piping para awk ou perl de uma linha e, como resultado, contêm aspas simples e $ 's. não fui capaz de descobrir uma regra rígida e rápida para fazer as citações corretamente, nem encontrei uma boa referência para isso. por exemplo, considere o seguinte:</p><pre><code># what i'd run locally: cmd='pgrep -fl java | grep -i datanode | awk '{print $1}' # this works with ssh $host "$cmd": cmd='pgrep -fl java | grep -i datanode | awk '"'"'{print $1}'"'" </code></pre><p>(observe as aspas extras na instrução awk.)</p><p>mas como faço para que isso funcione, por exemplo, <code>ssh $host "sudo su user -c '$cmd'"</code>? existe uma receita geral para gerenciar cotações em tais cenários? ..</p>
<p>lidar com vários níveis de citação (na verdade, vários níveis de análise/interpretação) pode ser complicado. isso ajuda a manter algumas coisas em mente:</p><ul> <li>cada “nível de citação” pode envolver potencialmente uma linguagem diferente.</li> <li>as regras de cotação variam de acordo com o idioma.</li> <li>ao lidar com mais de um ou dois níveis aninhados, geralmente é mais fácil trabalhar "de baixo para cima" (ou seja, do interior para o exterior).</li> </ul><h1>níveis de citação</h1><p>vejamos seus comandos de exemplo.</p><pre><code>pgrep -fl java | grep -i datanode | awk '{print $1}' </code></pre><p>seu primeiro exemplo de comando (acima) usa quatro idiomas: seu shell, o regex em <em> pgrep </em>, o regex em <em> grep </em> (que pode ser diferente da linguagem regex em <em> pgrep </em>) e <em> awk </em>. existem dois níveis de interpretação envolvidos: o shell e um nível após o shell para cada um dos comandos envolvidos. existe apenas um nível explícito de citação (shell citação em <em> awk </em>).</p><pre><code>ssh host … </code></pre><p>em seguida, você adicionou um nível de <em> ssh </em> no topo. este é efetivamente outro nível de shell: <em> ssh </em> não interpreta o comando em si, ele o entrega a um shell na extremidade remota (via (por exemplo) <code>sh -c …</code>) e que shell interpreta a string.</p><pre><code>ssh host "sudo su user -c …" </code></pre><p>então, você perguntou sobre a adição de outro nível de shell no meio usando <em> su </em> (via <em> sudo </em>, que não interpreta seus argumentos de comando, portanto, podemos ignorá-lo). neste ponto, você tem três níveis de aninhamento em andamento (<em> awk </em> → shell, shell → shell (<em> ssh </em>), shell → shell (<em> su user -c </em>), então aconselho usar a abordagem “de baixo para cima”. vou assumir que seus shells são compatíveis com bourne (por exemplo <em> sh </em>, <em> ash </em> , <em> traço </em>, <em> ksh </em>, <em> bash </em>, <em> zsh </em>, etc.). algum outro tipo de shell (<em> fish </em>, <em> rc </em>, etc.) pode exigir sintaxe diferente, mas o método ainda se aplica.</p><h1>debaixo para cima</h1><ol> <li>formule a string que deseja representar no nível mais interno.</li> <li>selecione um mecanismo de citações do repertório de citações do idioma seguinte.</li> <li>cite a string desejada de acordo com o mecanismo de cotação selecionado. <ul> <li>freqüentemente, há muitas variações de como aplicar qual mecanismo de cotação. fazer manualmente é geralmente uma questão de prática e experiência. ao fazer isso de forma programática, geralmente é melhor escolher o mais fácil de acertar (geralmente o “mais literal” (menos escapes)).</li> </ul> </li> <li>opcionalmente, use a string entre aspas resultante com código adicional.</li> <li>se você ainda não atingiu o nível desejado de citação/interpretação, pegue a string entre aspas resultante (mais qualquer código adicionado) e use-a como string inicial na etapa 2.</li> </ol><h1>a semântica das citações varia</h1><p>o que se deve ter em mente aqui é que cada idioma (nível de citação) pode fornecer semânticas ligeiramente diferentes (ou mesmo semânticas drasticamente diferentes) para o mesmo personagem de citação.</p><p>a maioria das linguagens tem um mecanismo de citação “literal”, mas eles variam exatamente em quão literais são. a aspa simples de shells do tipo bourne é literal (o que significa que você não pode usá-la para citar um caractere de aspas simples). outras linguagens (perl, ruby) são menos literais porque interpretam <strong>algumas</strong> sequências de barra invertida dentro de regiões entre aspas simples não literalmente (especificamente, <code>\\</code> e <code>\'</code> resulta em <code>\</code> e <code>'</code>, mas outras sequências de barra invertida são, na verdade, literais).</p><p>você terá que ler a documentação de cada um de seus idiomas para entender suas regras de cotação e a sintaxe geral.</p><h1>seu exemplo</h1><p>o nível mais interno do seu exemplo é um programa <em> awk </em>.</p><pre><code>{print $1} </code></pre><p>você vai incorporar isso em uma linha de comando do shell:</p><pre><code>pgrep -fl java | grep -i datanode | awk … </code></pre><p>precisamos proteger (no mínimo) o espaço e o <code>$</code> no programa <em> awk </em>. a escolha óbvia é usar aspas simples no shell em todo o programa.</p><ul> <li><code>'{print $1}'</code></li> </ul><p>no entanto, existem outras opções:</p><ul> <li><code>{print\ \$1}</code> escape diretamente do espaço e <code>$</code></li> <li><code>{print' $'1}</code> aspas simples apenas o espaço e <code>$</code></li> <li><code>"{print \$1}"</code> aspas duplas o todo e escapar de <code>$</code></li> <li><code>{print" $"1}</code> aspas duplas apenas o espaço e <code>$</code><br> isso pode estar distorcendo um pouco as regras (sem escape <code>$</code> no final de uma string entre aspas duplas é literal), mas parece funcionar na maioria dos shells.</li> </ul><p>se o programa usasse uma vírgula entre as chaves de abertura e fechamento, também precisaríamos citar ou escapar a vírgula ou as chaves para evitar a “expansão da chave” em alguns shells.</p><p>nós escolhemos <code>'{print $1}'</code> e incorporá-lo ao resto do “código” shell:</p><pre><code>pgrep -fl java | grep -i datanode | awk '{print $1}' </code></pre><p>em seguida, você queria executar isso via <em> su </em> e <em> sudo </em>.</p><pre><code>sudo su user -c … </code></pre><p><code>su user -c …</code> é como <code>some-shell -c …</code> (exceto rodando em algum outro uid), então <em> su </em> apenas adiciona outro nível de shell. <em> sudo </em> não interpreta seus argumentos, então não adiciona nenhum nível de citação.</p><p>precisamos de outro nível de shell para nossa string de comando. podemos escolher aspas simples novamente, mas temos que dar tratamento especial às aspas simples existentes. a maneira usual é assim:</p><pre><code>'pgrep -fl java | grep -i datanode | awk '\''{print $1}'\' </code></pre><p>existem quatro strings aqui que o shell irá interpretar e concatenar: a primeira string entre aspas simples (<code>pgrep … awk</code>), uma aspa simples de escape, o programa de aspas simples <em> awk </em>, outra aspa simples de escape.</p><p>existem, é claro, muitas alternativas:</p><ul> <li><code>pgrep\ -fl\ java\ \|\ grep\ -i\ datanode\ \|\ awk\ \'{print\ \$1}</code> fuja de tudo que é importante</li> <li><code>pgrep\ -fl\ java\|grep\ -i\ datanode\|awk\ \'{print\$1}</code> o mesmo, mas sem espaços em branco supérfluos (mesmo no programa <em> awk </em>!)</li> <li><code>"pgrep -fl java | grep -i datanode | awk '{print \$1}'"</code> aspas duplas, escape de <code>$</code></li> <li><code>'pgrep -fl java | grep -i datanode | awk '"'"'{print \$1}'"'"</code> sua variação; um pouco mais longo do que o normal devido ao uso de aspas duplas (dois caracteres) em vez de escapes (um caractere)</li> </ul><p>usar citações diferentes no primeiro nível permite outras variações neste nível:</p><ul> <li><code>'pgrep -fl java | grep -i datanode | awk "{print \$1}"'</code></li> <li><code>'pgrep -fl java | grep -i datanode | awk {print\ \$1}'</code></li> </ul><p>incorporar a primeira variação na linha de comando <em> sudo </em>/* su * fornece o seguinte:</p><pre><code>sudo su user -c 'pgrep -fl java | grep -i datanode | awk '\''{print $1}'\' </code></pre><p>você pode usar a mesma string em qualquer outro contexto de nível de shell (por exemplo, <code>ssh host …</code>).</p><p>em seguida, você adicionou um nível de <em> ssh </em> no topo. este é efetivamente outro nível de shell: <em> ssh </em> não interpreta o comando em si, mas o entrega a um shell na extremidade remota (via (por exemplo) <code>sh -c …</code>) e que shell interpreta a string.</p><pre><code>ssh host … </code></pre><p>o processo é o mesmo: pegue a string, escolha um método de cotação, use-a, incorpore-a.</p><p>usando aspas simples novamente:</p><pre><code>'sudo su user -c '\''pgrep -fl java | grep -i datanode | awk '\'\\\'\''{print $1}'\'\\\' </code></pre><p>agora, existem onze strings que são interpretadas e concatenadas: <code>'sudo su user -c '</code>, aspas simples com escape, <code>'pgrep … awk '</code>, aspas simples de escape, barra invertida de escape, duas aspas simples de escape, o programa entre aspas simples <em> awk </em>, aspas simples de escape, barra invertida de escape e um aspas simples com escape final.</p><p>a forma final é parecida com esta:</p><pre><code>ssh host 'sudo su user -c '\''pgrep -fl java | grep -i datanode | awk '\'\\\'\''{print $1}'\'\\\' </code></pre><p>é um pouco complicado digitar à mão, mas a natureza literal da citação única do shell torna mais fácil automatizar uma ligeira variação:</p><pre><code>#!/bin/sh sq() { # single quote for bourne shell evaluation # change ' to '\'' and wrap in single quotes. # if original starts/ends with a single quote, creates useless # (but harmless) '' at beginning/end of result. printf '%s\n' "$*" | sed -e "s/'/'\\\\''/g" -e 1s/^/\'/ -e \$s/\$/\'/ } # some shells (ksh, bash, zsh) can do something similar with %q, but # the result may not be compatible with other shells (ksh uses $'...', # but dash does not recognize it). # # sq() { printf %q "$*"; } ap='{print $1}' s1="pgrep -fl java | grep -i datanode | awk $(sq "$ap")" s2="sudo su user -c $(sq "$s1")" ssh host "$(sq "$s2")" </code></pre>
<p>que tal usar o comando <code>su</code>?</p><pre><code>$ whoami user1 $ su - user2 password: $ whoami user2 $ exit logout </code></pre><p>se você deseja fazer login como root, não há necessidade de especificar o nome de usuário:</p><pre><code>$ whoami user1 $ su - password: $ whoami root $ exit logout </code></pre><p>geralmente, você pode usar <code>sudo</code> para iniciar um novo shell como o usuário que você deseja; a <code>-u</code> flag permite especificar o nome de usuário que você deseja:</p><pre><code>$ whoami user1 $ sudo -u user2 zsh $ whoami user2 </code></pre><p>existem maneiras mais tortuosas se você não tiver acesso ao sudo, como ssh username @ localhost, mas <code>sudo</code> é provavelmente o mais simples, desde que esteja instalado e você tenha permissão para usá-lo.</p> <p>tente isso</p><pre><code>create procedure simpleproc (in name varchar(50),in user\_name varchar(50),in branch varchar(50)) begin insert into student (name,user\_name,branch) values (name ,user\_name,branch); end </code></pre> <p>você não pode usar <code>\q</code> em uma sequência de aspas simples/não interpolada. deve ser visto pelo lexer.</p><p>de qualquer forma, til não é um meta-personagem.</p><p>adicionar <code>use regex "debug"</code> e você verá o que realmente está acontecendo.</p> <p>tente fazer isso (requer <code>bash --version</code>&gt; = 4):</p><pre><code>shopt -s globstar rename -n 's/special/regular/' ** </code></pre><p>remova a opção <code>-n</code> quando seus testes estiverem ok</p><p><img src="https://pix.toile-libre.org/upload/original/1377510865.png" alt="warning"> <strong>existem outras ferramentas com o mesmo nome que podem ou não ser capazes de fazer isso, então seja cuidadoso.</strong><br> <br/></p><p>se você executar o seguinte comando (<code>gnu</code>)</p><pre><code>$ file "$(readlink -f "$(type -p rename)")" </code></pre><p>e você tem um resultado como </p><pre><code>.../rename: perl script, ascii text executable </code></pre><p>e não contendo:</p><pre><code>elf </code></pre><p>então esta parece ser a ferramenta certa =)</p><p>se não, para torná-lo o padrão (geralmente já o caso) em <code>debian</code> e derivado como <code>ubuntu</code>:</p><pre><code>$ sudo update-alternatives --set rename /path/to/rename </code></pre><p>(substitua <code>/path/to/rename</code> pelo caminho do seu comando <code>perl's rename</code>.</p><hr><p>se você não tiver este comando, procure em seu gerenciador de pacotes para instalá-lo ou <a href="https://metacpan.org/module/rmbarker/file-rename-0.20/rename.pl">faça-o manualmente</a> </p><hr><p>por último, mas não menos importante, esta ferramenta foi originalmente escrita por larry wall, o pai do perl.</p> <p>atualização: * é sintaxe válida, mas não é necessário. você pode descobrir mais <a href="http://httpd.apache.org/docs/2.0/mod/core.html#servername">aqui</a> .</p><p>isso vai funcionar embora.</p><pre><code>&lt;virtualhost *:80&gt; servername example.com &lt;/virtualhost&gt; &lt;virtualhost *:80&gt; servername www.example.com &lt;/virtualhost&gt; </code></pre><p>a primeira diretiva corresponderá a tudo o que não é explicitamente definido em outro lugar.</p> acredito que ele esteja falando o seguinte, o ssh é um protocolo de rede que serve para “acessar” de forma “segura” uma maquina.

porém existe o ssh- client e ssh-sever, no caso ele disse para instalar o ssh-server, que tem como função “servir” um acesso ssh (e não vem instalado por padrão).

já o s… <p>assumindo o sql server 2005+ um exemplo de como obter<strong> apenas </strong>a segunda linha (que eu acho que você pode estar perguntando - e é a razão pela qual <code>top</code> não funcionará para você?)</p><pre><code>set statistics io on ;with cte as ( select * , row\_number() over (order by number) as rn from master.dbo.spt\_values ) select * from cte where rn=2 /*just to add in what i was running re: comments*/ ;with cte as ( select top 2 * , row\_number() over (order by number) as rn from master.dbo.spt\_values ) select * from cte where rn=2 </code></pre> <p>enviar uma nova linha <code>\n</code> executará o comando. <code>.end()</code> sairá do shell.</p><p>modifiquei o exemplo para trabalhar com o bash enquanto estou no osx.</p><pre><code>var terminal = require('child\_process').spawn('bash'); terminal.stdout.on('data', function (data) { console.log('stdout: ' + data); }); terminal.on('exit', function (code) { console.log('child process exited with code ' + code); }); settimeout(function() { console.log('sending stdin to terminal'); terminal.stdin.write('echo "hello $user. your machine runs since:"\n'); terminal.stdin.write('uptime\n'); console.log('ending terminal session'); terminal.stdin.end(); }, 1000); </code></pre><p>a saída será:</p><pre><code>sending stdin to terminal ending terminal session stdout: hello root. your machine runs since: stdout: 9:47 up 50 mins, 2 users, load averages: 1.75 1.58 1.42 child process exited with code 0 </code></pre> Opção 1 é de longe o padrão. A fraqueza texto simples geralmente é superado pela aplicação SSL durante o login para que a senha é, pelo menos criptografados durante o trânsito.


**Edit:** Eu sugiro que você siga a resposta aceitos para essa pergunta.


Não se esqueça de exigir um [nonce](http://en.wikipedia.org/wiki/Cryptographic_nonce) para o seu pedido. Isso ajudará a protegê-lo contra ataques de repetição.


**Editar o segundo:** Wayne cuidadosamente mencionou que você deve [sal](https://stackoverflow.com/questions/674904/salting-your-password-best-practices) sua senha antes de hash. Aqui estão algumas dicas básicas:


1. Não importa se o seu sal é um prefixo, postfix, ou infix
2. Seu sal deve ser grande, aleatório, e complexo.
3. Seu sal deve ser único por valor salgada. O sal em si não precisa ser criptografados. <p>na página do manual <code>ps</code>:</p><blockquote> <p>-e selecione todos os processos. idêntico a -a.</p> </blockquote><p>portanto, <code>ps -e</code> exibirá todos os processos. as opções comuns para "me dê tudo" são <code>ps -ely</code> ou <code>ps aux</code>, o último é o estilo bsd. frequentemente, as pessoas canalizam essa saída para <code>grep</code> para procurar um processo, como na resposta do xenoterracide. para evitar também ver <code>grep</code> na saída, você verá frequentemente algo como:</p><pre><code> ps -ef | grep [f]oo </code></pre><p>onde foo é o nome do processo que você está procurando.</p><p>no entanto, se você estiver procurando por um processo específico, recomendo usar o comando <code>pgrep</code> se estiver disponível. acredito que esteja disponível no ubuntu server. usar <code>pgrep</code> significa evitar a condição de corrida mencionada acima. ele também fornece alguns outros recursos que exigiriam truques <code>grep</code> cada vez mais complicados para serem replicados. a sintaxe é simples:</p><pre><code>pgrep foo </code></pre><p>onde foo é o processo pelo qual você está procurando. por padrão, ele simplesmente emitirá o id do processo (pid) do processo, se encontrar um. vejo <code>man pgrep</code> para outras opções de saída. achei a seguinte página muito útil:</p><p> <a href="http://mywiki.wooledge.org/processmanagement">http://mywiki.wooledge.org/processmanagement</a> </p>