Bash script problem...

Hi,

I am trying to output the contents of PASS below to a file but the file is always blank even though PASS has a value… I have tried everything. It always comes out blank. You run the script as follows:

sh scriptname.sh Tom Thumb

Here is the script:


#!/bin/sh

FIRSTNAME="$(echo "$1" | tr [a-z] [A-Z])"
SURNAME="$(echo "$2" | tr [a-z] [A-Z])"
CLIENT=$SURNAME"_"$FIRSTNAME
PASS=</dev/urandom tr -dc A-Za-z0-9| (head -c $1 > /dev/null 2>&1 || head -c 8)
FILE="$CLIENT.txt"

# create password file
touch $FILE

# write password to file

echo ${PASS} > ${FILE}

$PASS definitely has a value. I have echoed it to the screen… any help would be great. This is driving me mad!

/jlar

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Running your command which sets ‘$PASS’ I get no value. Are you sure
that is working properly? Perhaps you should echo /dev/urandom and then
run the other stuff against data there.

Good luck.

eeijlar wrote:
> Hi,
>
> I am trying to output the contents of PASS below to a file but the file
> is always blank even though PASS has a value… I have tried everything.
> It always comes out blank. You run the script as follows:
>
>
> Code:
> --------------------
> sh scriptname.sh Tom Thumb
> --------------------
>
>
> Here is the script:
>
>
> Code:
> --------------------
>
> #!/bin/sh
>
> FIRSTNAME="$(echo “$1” | tr [a-z] [A-Z])"
> SURNAME="$(echo “$2” | tr [a-z] [A-Z])"
> CLIENT=$SURNAME"_"$FIRSTNAME
> PASS=</dev/urandom tr -dc A-Za-z0-9| (head -c $1 > /dev/null 2>&1 || head -c 8)
> FILE="$CLIENT.txt"
>
> # create password file
> touch $FILE
>
> # write password to file
>
> echo ${PASS} > ${FILE}
> --------------------
>
>
> $PASS definitely has a value. I have echoed it to the screen… any
> help would be great. This is driving me mad!
>
> /jlar
>
>
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD4DBQFI4k+d3s42bA80+9kRArWSAJ4rqNlWrrcn0vwEvUCMrYb0tbvIigCYztwb
xxf4uzpdeePHI0jFMeieKA==
=AVTi
-----END PGP SIGNATURE-----

Hi

Thanks for your reply… I think it has a value…

It echoes to the screen, if you run this instead:

FIRSTNAME="$(echo "$1" | tr [a-z] [A-Z])"
SURNAME="$(echo "$2" | tr [a-z] [A-Z])"
CLIENT=$SURNAME"_"$FIRSTNAME
PASS=</dev/urandom tr -dc A-Za-z0-9| (head -c $1 > /dev/null 2>&1 || head -c 8)
FILE="$CLIENT.txt"

# create password file
touch $FILE

echo $PASS
# write password to file

echo ${PASS} > ${FILE}

not to a file though… I need it to be a variable as I need it in later in the script. I only posted the bit I couldn’t get working here…

PASS=</dev/urandom tr -dc A-Za-z0-9| (head -c $1 > /dev/null 2>&1 || head -c 8)

This is just gibberish shell code. And I’m being charitable.

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I still can’t make it work… but the following works just fine (all on
one line):

PASS=cat /dev/urandom |tr -dc A-Za-z0-9| (head -c $1 > /dev/null 2>&1 || head -c 8)

Good luck.

eeijlar wrote:
> Hi
>
> Thanks for your reply… I think it has a value…
>
> It echoes to the screen, if you run this instead:
>
>
> Code:
> --------------------
> FIRSTNAME="$(echo “$1” | tr [a-z] [A-Z])"
> SURNAME="$(echo “$2” | tr [a-z] [A-Z])"
> CLIENT=$SURNAME"_"$FIRSTNAME
> PASS=</dev/urandom tr -dc A-Za-z0-9| (head -c $1 > /dev/null 2>&1 || head -c 8)
> FILE="$CLIENT.txt"
>
> # create password file
> touch $FILE
>
> echo $PASS
> # write password to file
>
> echo ${PASS} > ${FILE}
> --------------------
>
>
> not to a file though… I need it to be a variable as I need it in
> later in the script. I only posted the bit I couldn’t get working here…
>
>
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFI4lcN3s42bA80+9kRAjyqAJ9seLNTT4xE8EGPwOWQhqV2SjpZxACfRV2F
sBPPvui6/G7j3Dzw6YCIoKE=
=rWqc
-----END PGP SIGNATURE-----

Perhaps… but you should see the other scripts to generate random numbers… 500 lines. This seemed the simplest which I’m always in favour of :slight_smile:

The problem is your code doesn’t even do what you think it does. A 500 line program that works is still better than a 1-liner that doesn’t. Not that I think this task needs 500 lines.

Hi ken_yap,

I am used to Perl and Shell scripting seems very limited (at least I think so!) after using Perl. I found a Perl script that does the trick… I am sure you can do the same in Shell.

Thanks for your help…

/jlar


sub randomPassword {
 my $password;
 my $_rand;

 my $password_length = $_[0];
 if (!$password_length) {
  $password_length = 10;
 }

 my @chars = split(" ",
 "a b c d e f g h i j k l m n o
  p q r s t u v w x y z A B C D
  E F G H I J K L M N O P Q R S
  T U V W X Y Z 0 1 2 3 4 5 6 7 8 9");

 srand;

 for (my $i=0; $i <= $password_length ;$i++) {
  $_rand = int(rand 71);
  $password .= $chars$_rand];
 }
 return $password;
}

The problem in your code is the line where you compute PASS.
In your script it is

PASS=</dev/urandom tr -dc A-Za-z0-9| (head -c $1 > /dev/null 2>&1 || head -c 8)

It should be


PASS=`&lt;/dev/urandom tr -dc A-Za-z0-9| (head -c $1 &gt; /dev/null 2&gt;&1 || head -c 8)`

Notice the back quotes around the command. Modify this line and your shell script should work fine. Hope that helps.

Shell scripting is very powerful.You can find more tips and tricks here
Thejaswi Raya: Shell Scripting

  • Thejaswi Raya

In addition to my previous post, you can also use this piece of code to compute PASS


PASS=`cat /dev/urandom | tr -dc a-zA-Z0-9 | head -c 8`

This I feel is more readable and you really dont need “head -c $1 > /dev/null 2>&1”. Just a suggestion.

  • Thejaswi Raya

What thejaswihr said:

Let’s look at what your line actually meant to the shell.

PASS=</dev/urandom tr -dc A-Za-z0-9| (head -c $1 > /dev/null 2>&1 || head -c 8)
PASS=

Set PASS to the empty string.

</dev/random tr -dc A-Za-z0-9

Run tr, reading from /dev/random.

(head -c $1 > /dev/null 2>&1 || head -c 8)

Pipe to a shell which runs the command head -c $1 but if that command fails (exits with non-zero status due to some mistake in options, perhaps), run the second head command. Hint: || is the logical or operator, not a pipe.

So there were two major mistakes in your line, you didn’t capture the output of the commands into PASS (which is why the output went to the terminal), and your use of || was questionable.

So it’s back to bash syntax class for you. :wink:

Incidentally this is slightly shorter:

PASS=`tr -dc a-zA-Z0-9 &lt; /dev/random | head -c 8`

@OP, there are examples on creating random numbers here