2014-09-26 10 views
5

I seguenti script di bash e Perl forniscono misteriosamente risultati diversi. Perché?perl shasum vs bash shasum

#!/bin/bash                  
hash=`echo -n 'abcd' | /usr/bin/shasum -a 256`; 
echo $hash; 

#!/usr/bin/perl                 
$hash = `echo -n 'abcd' | /usr/bin/shasum -a 256`; 
print "$hash"; 

Lo script bash:

$ ./tst.sh 
88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589 - 

Lo script Perl:

$ ./tst.pl 
61799467ee1ab1f607764ab36c061f09cfac2f9c554e13f4c7442e66cbab9403 - 

diamine?

+0

Assegnare il percorso completo a 'echo'. Altrimenti userete il bash built-in in un caso, e possibilmente qualcos'altro nell'altro caso. – ThisSuitIsBlackNot

+5

Sei pignolo: i 2 hanno in sé più o meno gli stessi 16 caratteri ;-) –

+0

Sì. Usato '/ bin/echo' - questo genere di cose mi tiene sveglio la notte. – wcochran

risposta

17

Sommario: Nello script Perl, -n viene trattato come un argomento da includere nell'output di echo, non una bandiera di sopprimere la nuova riga. (Prova

$hash = `echo -n 'abcd'`; 

confermare). Utilizzare invece printf.


Perl utilizza /bin/sh per eseguire codice in tic schiena. Anche se /bin/sh è un collegamento a bash, si comporterà diversamente quando invocato tramite simile. In modalità POSIX,

echo -n 'abcd' 

uscita volontà

-n abcd 

che è, l'opzione -n non è riconosciuto come una bandiera per sopprimere un ritorno a capo, ma viene trattato come un argomento normale per la stampa. Sostituire echo -n con printf in ogni script e si dovrebbe ottenere lo stesso hash SHA da ogni script.

(AGGIORNATO: bash 3.2, quando invocato come sh, visualizza questo comportamento.Le versioni più recenti di bash sembrano continuare a trattare -n come un flag quando invocato come sh.)


Ancora meglio, non sborsare per fare le cose che si possono fare in Perl.

use Digest::SHA; 

$hash = Digest::SHA::sha256('abcd'); 

Per i curiosi, ecco cosa POSIX spec has to say su echo. Non sono sicuro su cosa fare della conformità XSI; bashecho richiede l'opzione -e per trattare i caratteri di escape specialmente, ma quasi tutti i serbatoi — tranne vecchie versioni di bash, e quindi solo in casi particolari — trattano le -n come flag, non una stringa. Oh bene.

The following operands shall be supported: 

string 
A string to be written to standard output. If the first operand is -n, or 
if any of the operands contain a <backslash> character, the results are 
implementation-defined. 

On XSI-conformant systems, if the first operand is -n, it shall be treated 
as a string, not an option. The following character sequences shall be 
recognized on XSI-conformant systems within any of the arguments: 

\a 
Write an <alert>. 
\b 
Write a <backspace>. 
\c 
Suppress the <newline> that otherwise follows the final argument in the output. All characters following the '\c' in the arguments shall be ignored. 
\f 
Write a <form-feed>. 
\n 
Write a <newline>. 
\r 
Write a <carriage-return>. 
\t 
Write a <tab>. 
\v 
Write a <vertical-tab>. 
\\ 
Write a <backslash> character. 
\0num 
Write an 8-bit value that is the zero, one, two, or three-digit octal number num. 
+0

Mi hai catturato mentre cercavo su quale modulo facesse le somme SHA :) – chepner

+0

Interessante, sulla mia macchina (che probabilmente ha una versione leggermente personalizzata di 'bash', ma è la versione 4.3.25+), eseguendo' sh -c "echo - n 'abcd' "' produce lo stesso risultato di 'bash -c" echo -n 'abcd' "' (senza una nuova riga e senza un '-n' nell'output). –

+0

Sì, penso che questo potrebbe essere stato un piccolo errore nelle versioni precedenti di 'bash'. Anche in 3.2, 'bash --posix -c 'echo -n abcd'' tratta' -n' come una bandiera, contro 'sh -c' echo -n abcd'' che non lo fa. – chepner

6

Se lo fai:

printf "%s" 'abcd' | /usr/bin/shasum -a 256 

si ottiene l'hash 88d ... 589. Se lo fai:

printf "%s\n" '-n abcd' | /usr/bin/shasum -a 256 

si ottiene l'hash 617 ... 403.

Pertanto, deduco che Perl è in qualche modo esegue un comando diverso echo, forse /bin/echo o /usr/bin/echo invece del bash incorporato echo, o forse incorporato eco /bin/sh (che potrebbe forse dash anziché bash) e questo altro echo non riconosce l'opzione -n come opzione e genera dati diversi.

Non sono sicuro quale altro echo stia rilevando; sulla mia macchina che esegue una LTE derivato Ubuntu 14.04, bash, dash, sh (legato alla bash), ksh, csh e tcsh tutto trattare echo -n abcd allo stesso modo. Ma da qualche parte lungo la linea, penso che stia succedendo qualcosa in questo senso; il checksum hash identico punta fortemente ad esso. (Forse hai un 3.2 bash legato alla sh, vedi le note nei commenti.)

+0

Quando invocato come 'sh',' bash' 3.2 non riconosce '-n' come un flag, ma' bash' 4.1 e successive (e forse anche 4.0, probabilmente) lo fanno. Il tuo 'sh' potrebbe essere collegato a una versione più recente di' bash', sebbene io di solito fosse collegato a 'dash' in Ubuntu. – chepner

+0

Quello che sto usando non è una versione Ubuntu 14.04 completamente standard; è stato riprogettato in parte dalla società. Il 'bash' è riparato con la correzione di Shell Shock, sebbene la sua versione asserisca di essere' 4.3.11 (1) ', e'/bin/sh' _is_ un collegamento a '/ bin/bash'. (Ci sono altre stranezze riguardo la data di rilascio rispetto a Shell Shock, ma la versione base di Shell Shock mostra l'output "fisso".) –

+0

Ho sostituito 'echo' con'/bin/echo' e la differenza è andata via. Grazie. – wcochran

Problemi correlati