Generate valid Unix username and password in Perl - perl

I need to generate a username and password pair in order to create user on a Unix system, preferably a pair that would be hard to guess (for security). Does anyone know any good way of doing this using Perl?
UPDATE
So I kind of combined some of the answers below and did some of my own stuff, and this it what I ended up getting. Now these generated usernames and passwords are kind of cryptic and not easy to remember, which is what I was looking for. However, if you're looking for more readable generation, you'll have to tweak it to your liking.
use String::Random qw(random_regex);
use Data::Random::WordList;
my $user = random_regex('\w{3,6}\d{3,6}\w{3,7}') . time . int(rand(1000));
my $wl = new Data::Random::WordList( wordlist => '/usr/share/dict/words' );
my #rand_words = $wl->get_words(int(rand(3)) + 3);
$wl->close();
my $pass = join " ", #rand_words;
$pass .= ' ' . int(rand(1000)) . time;
my $crypt_pass = crypt($pass,'salt');
system "useradd -p $crypt_pass $user";
#you can now login with $user and $pass on your system

For generating password You can use:
$password = `date | md5sum | fold -w 10 | head -n 1`;
$password = crypt($password,'some_string');
It's actually more Bash than Perl but it does the job.

From http://sysadminsjourney.com/content/2009/09/16/random-password-generation-perl-one-liner/
perl -le 'print map { (a..z,A..Z,0..9)[rand 62] } 0..pop' 8
Will generate a random 8 character string from the characters a-z, A-Z and 0-9 .
You should be able to modify this to generate the username and password.
Username would be:
perl -le 'print map { ([a-z_][a-z0-9_][rand 62] } 0..pop' 30
The password would be similar, but you would need to use the passwd command to actually set it to the user. Not sure if Perl has an equivalent.

As mentioned by others , its more BASH than perl. Here is my way of generating the password:
passwd=`date +%s | sha256sum | base64 | head -1 | cut -c 1-8`

Related

quoting {print $NF} inside layers of single and double quotes?

Stuck trying to figure out how to single quotes withing single quotes within double quotes. Here's what I'm trying to do....
From perl, I want to run a system command that...
- does an ssh into a remote machine
- executes 'uptime' and then plucks the last field out of that (avg load last 15 min).
\#\!/usr/bin/env perl
my $cmd = "ssh othermachine 'uptime | awk '{print $NF}'' > local_file.dat";
system($cmd);
Of course this won't run ...
% ./try.pl
Missing }.
%
Missing "}" ??? Looks like it's interpreting the $NF} as a var? I tried escaping the {} chars with no luck. I tried escaping the $, no luck. I tried a space before the }, no luck but different msg (Undefined variable).
c-shell BTW and thanks in advance !
You want the following to be ssh's second argument:
uptime | awk '{print $NF}'
To do that, you simply placed single quotes around it. But that doesn't work because it contains single quotes.
You want to build a string that contains $NF, but you did it as follows:
"...$NF..."
That will place the value of (non-existent) Perl variable $NF in the string.
Do it step by step.
Static:
Remote command:
uptime | awk '{print $NF}'
Local command:
ssh othermachine 'uptime | awk '\''{print $NF}'\''' >local_file.dat
String literal:
my $local_cmd = q{ssh othermachine 'uptime | awk '\''{print $NF}'\''' >local_file.dat}
Dynamic:
use String::ShellQuote qw( shell_quote );
my $remote_cmd = q{uptime | awk '{print $NF}'};
my $local_cmd = shell_quote('ssh', 'othermachine', $remote_cmd) . ' >local_file.dat';
Use Net::OpenSSH and let it do the quoting for you:
use Net::OpenSSH;
my $ssh = Net::OpenSSH->new($othermachine,
remote_shell => 'tcsh');
$ssh->system({stdout_file => 'local_file.dat'},
'uptime', \\'|', 'awk', '{print $NF}')
or die "ssh command failed: " . $ssh->error;

Please Help. Variable not being interpolated in Net :: SCP

This code telnets to a remote machine, fetches a latest directory. Then the latest folder name is stored into a variable then scp from remote to local machine happens. But the scp part is not working.
#!/usr/bin/perl -w
use Net::Telnet;
use Net::SCP::Expect;
$telnet = new Net::Telnet ( Timeout=>10, Errmode=>'die');
$telnet->open('192.168.12.123');
$telnet->login("liam", "thegrey");
#output = $telnet->waitfor('/\$ $/i');
my #lines=$telnet->cmd('ls');
print"\t\tLOGIN IN SUCESS!!\n\n\n";
$telnet->cmd('cd vault');
print "\t\tThe latest file is >\n";
my #update;
#update=$telnet->cmd(
'ls -l| grep Latest| tail -5 | head -2 | tail -1|tr -s " " | cut -d " " -f9');
my $found=join("",#update);
print "$found"; #The required value is printed here.
my $scpe = Net::SCP::Expect->new(user=>'liam',password=>'thegrey');
#The $found variable is not being interpolated.
$scpe->scp("192.168.12.123:/root/vault/$found/latest/movie.mkv",
"/root/ashesh_assignment/movie.mkv");
That's not true. if $found contains the value xxx, then the string literal
"192.168.12.123:/root/vault/$found/latest/movie.mkv"
produces the string
192.168.12.123:/root/vault/xxx/latest/movie.mkv
Now, it wouldn't surprise me if $found contained a newline which would create an odd path. Maybe a chomp is in order?

Printing reverse complement of DNA in single-line Perl

I want to write a quick single-line perl script to produce the reverse complement of a sequence of DNA. The following isn't working for me, however:
$ cat sample.dna.sequence.txt | perl -ne '{while (<>) {$seq = $_; $seq =~ tr /atcgATCG/tagcTAGC/; $revComp = reverse($seq); print $revComp;}}'
Any suggestions? I'm aware that
tr -d "\n " < input.txt | tr "[ATGCatgcNn]" "[TACGtacgNn]" | rev
works in bash, but I want to do it with perl for the practice.
Your problem is that is that you're using both -n and while (<>) { }, so you end up with while (<>) { while (<>) { } }.
If you know how to do <file.txt, why did you switch to cat file.txt|?!
perl -0777ne's/\n //g; tr/ATGCatgcNn/TACGtacgNn/; print scalar reverse $_;' input.txt
or
perl -0777pe's/\n //g; tr/ATGCatgcNn/TACGtacgNn/; $_ = reverse $_;' input.txt
Or if you don't need to remove the newlines:
perl -pe'tr/ATGCatgcNn/TACGtacgNn/; $_ = reverse $_;' input.txt
If you need to use cat, the following one liner should work for you.
ewolf#~ $cat foo.txt
atNgNt
gatcGn
ewolf#~ $cat foo.txt | perl -ne '$seq = $_; $seq =~ tr/atcgATCG/tagcTAGC/;print reverse( $seq )'
taNcNa
ctagCn
Considering the DNA sequences in single-line format in a multifasta file:
cat multifasta_file.txt | while IFS= read L; do if [[ $L == >* ]]; then echo "$L"; else echo $L | rev | tr "ATGCatgc" "TACGtacg"; fi; done > output_file.txt
If your multifasta file is not in single-line format, you can transform your file to single-line before using the command above, like this:
awk '/^>/ {printf("\n%s\n",$0);next; } { printf("%s",$0);} END {printf("\n");}' <multifasta_file.txt >multifasta_file_singleline.txt<="" p="">
Then,
cat multifasta_file_SingleLine.txt | while IFS= read L; do if [[ $L == >* ]]; then echo "$L"; else echo $L | rev | tr "ATGCatgc" "TACGtacg"; fi; done > output_file.txt
Hope it is useful for someone. It took me some time to build it.
The problem is that you're using -n in the perl flag, yet you've written your own loop. -n wraps your supplied code in a while loop like while(<STDIN>){...}. So the STDIN file handle has already been read from and your code does it again, getting EOF (end of file) or rather 'undefined'. You either need to remove the n from -ne or remove the while loop from your code.
Incidentally, a complete complement tr pattern, including ambiguous bases, is:
tr/ATGCBVDHRYKMatgcbvdhrykm/TACGVBHDYRMKtacgvbhdyrmk/
Ambiguous bases have complements too. For example, a V stands for an A, C, or G. Their complements are T, G, and C, which is represented by the ambiguous base B. Thus, V and B are complementary.
You don't need to include any N's or n's in your tr pattern (as was demonstrated in another answer) because the complement is the same and leaving them out will leave them untouched. It's just extra processing to put them in the pattern.

How to strip characters within a filename?

I am having trouble on stripping characters within a filename.
For example:
1326847080_MUNDO-Cinco-Cosas-Que-Aprendimos-Del-Debate-De-Los-Republicanos-1.xml
1326836220_PLANETACNN-Una-Granja-De-Mariposas-Ayuda-A-Reducir-La-Tala-De-Bosques-En-Tanzania-3.xml
This is the output I want:
1326847080_MUNDO-1.xml
1326836220_PLANETACNN-3.xml
for i in *.xml
do
j=$(echo $i | sed -e s/-.*-/-/)
echo mv $i $j
done
or in one line:
for i in *.xml; do echo mv $i $(echo $i | sed -e s/-.*-/-/); done
remove echo to actually perform the mv command.
Or, without sed, using bash builtin pattern replacement:
for i in *.xml; do echo mv $i ${i//-*-/-}; done
rename to the rescue, with Perl regular expressions. This command will show which moves will be made; just remove -n to actually rename the files:
$ rename -n 's/([^-]+)-.*-([^-]+)/$1-$2/' *.xml
1326836220_PLANETACNN-Una-Granja-De-Mariposas-Ayuda-A-Reducir-La-Tala-De-Bosques-En-Tanzania-3.xml renamed as 1326836220_PLANETACNN-3.xml
1326847080_MUNDO-Cinco-Cosas-Que-Aprendimos-Del-Debate-De-Los-Republicanos-1.xml renamed as 1326847080_MUNDO-1.xml
The regular expression explained:
Save the part up to (but excluding) the first dash as match 1.
Save the part after the last dash as match 2.
Replace the part from the start of match 1 to the end of match 2 with match 1, a dash, and match 2.
sorry for the late reply , but i saw it today :( .
I think you are looking for the following
input file ::
cat > abc
1326847080_MUNDO-Cinco-Cosas-Que-Aprendimos-Del-Debate-De-Los-Republicanos-1.xml
1326836220_PLANETACNN-Una-Granja-De-Mariposas-Ayuda-A-Reducir-La-Tala-De-Bosques-En-Tanzania-3.xml
code : (its a bit too basic , even for my liking)
while read line
do
echo $line ;
fname=`echo $line | cut -d"-" -f1`;
lfield=`echo $line | sed -n 's/\-/ /gp' | wc -w`;
lname=`echo $line | cut -d"-" -f${lfield}`;
new_name="${fname}-${lname}";
echo "new name is :: $new_name";
done < abc ;
output ::
1326847080_MUNDO-Cinco-Cosas-Que-Aprendimos-Del-Debate-De-Los-Republicanos-1.xml
new name is :: 1326847080_MUNDO-1.xml
1326836220_PLANETACNN-Una-Granja-De-Mariposas-Ayuda-A-Reducir-La-Tala-De-Bosques-En-Tanzania-3.xml
new name is :: 1326836220_PLANETACNN-3.xml

Intersystems Cache SQL shell: How to spool the output of a query to a file?

I am trying to create a script in UNIX to query the Cache database. I could get the output but how do I write the output to a file>
I used the following procedure:
cache << EOF
DO \$SYSTEM.SQL.Shell()
SELECTMODE DISPLAY
SELECT * from .....
GO
EXIT
EOF
If you are using this for reports/webpages/etc I would look at the built in modules that Intersystems provides for Perl, Python, Ruby, etc. These should give you a cleaner interface into the database.
That said, I do some external calls for monitoring purposes that don't use the language API because of what I am trying to get from the database (usually internals). In those cases I use Perl. I use Perl to because doing it this way I need to parse out the menus and other things I don't want (which you won't get with the APIs). The following is a simple example looking at all the users that exist in Cache.
#!/usr/bin/perl
use strict;
my $username = 'user';
my $password = 'password';
my $val = `csession $instance -U %SYS << done
$username
$password
d ^SECURITY
1
3
*
*
h
done`;
my #users = split(/\n/, $val);
my $in_users = 0;
my $output = '';
foreach (#users){
if($in_users){
chomp($_);
if($_ eq ''){
#no longer listing users
$in_users = 0;
} else {
$output .= "$_\n";
}
}
$in_users = 1 if($_ =~ m/^\-\-\-\-/); # I started a the user list
}
print $output; # this prints out to the console
#This prints to a file.
open(OUTFILE, ">outfile.txt");
print OUTFILE $output;
Check out the following links about the Perl and Python API
http://docs.intersystems.com/cache20102/csp/docbook/DocBook.UI.Page.cls?KEY=GBPL
and
http://docs.intersystems.com/cache20102/csp/docbook/DocBook.UI.Page.cls?KEY=GBPY
It's a bit hackish, but the following should work:
echo -e "username\npassword\nDO \$SYSTEM.SQL.Shell()\nfoo\nbar\nH\n" | cache > output
Each command you would enter in Caché is followed by a "\n" to indicate a line return. That is then piped into a new session and its output is written to the file.