Friday, April 30, 2021

REGEX (Regular Expressions)

Start and end of line

        #  matches all line starting with "cat"

egrep '^cat' regex.txt

# matches all line ending with "cat"

egrep 'cat$' regex.txt

# matches all line that has "cat" anywhere on the line

egrep 'cat' regex.txt

# matches a line that contains only "cat"

egrep '^cat$' regex.txt

# matches empty lines

egrep '^$' regex.txt

# matches non-empty lines (-v is for negating the output)

egrep -v '^$' regex.txt

Single character match

       # there must be any single character betwen "a" and "c"

egrep 'a.c' regex.txt

Character class

        # matches "gray" or "grey"

egrep 'gr[ae]y' regex.txt

#  combining several character classes

egrep 'sep[ea]r[ea]te' regex.txt

# matches "<H1>", "<H2>", and "<H3>"

egrep '<H[123]>' regex.txt

# same as above ^ (provides a range)

egrep '<H[1-3]>' regex.txt

# matches "<H[-]>" (doesn't provide a range)

egrep '<H[-]>' regex.txt

# multiple ranges are fine

egrep '<H[0123456789abcdefABCDEF]>' regex.txt

# simplified version of the above ^ expression

egrep '<H[0-9a-fA-F]>' regex.txt

# matches a "!", ".", "_", and "?"

egrep '<H[!._?]>' regex.txt

# match if and only if there is something that is not

# "<Hx>" (remember this concept)

egrep '<H[^x]>' regex.txt

# matches all that are not "<H1>", "<H2>",

# or "<H3>"

egrep '<H[^1-3]>' regex.txt

Alternatives

        # matches "gray" or "grey"

egrep 'gray|grey' regex.txt

# same as above ^

egrep 'gr(a|e)y' regex.txt

# matches any line that begins with 'From: ',

# 'To: ', or 'Subject: '

egrep '^(From|To|Subject) ' regex.txt 

Word boundaries

        # matches all lines that have a string which starts with "cat"

egrep '\<cat' regex.txt

# matches all lines that have a string which ends with "cat"

egrep 'cat\>' regex.txt

# matches all lines only that have a word "cat" which is not

# embedded within another word (or string). e.g this will

# match line `the cat is furry` but not `concatenate this file`

egrep '\<cat\>' regex.txt

Optional items

        # matches lines with string "color" or "colour" ("u" is optional)

egrep 'colou?r' regex.txt

# same as `egrep '(July|Jul) (4th|four|4)' regex.txt`

egrep 'July? (four|4(th)?)'

# allows one optional space

egrep '<H1 ?>' regex.txt

Quantifiers: repetition

        # matches "<H1>", "<H1 >", "<H1  >", "<H1   >", and

# so on (no space, w/ one space, or w/ more than

# one space after H1)

egrep '<H1 *>' regex.txt

# matches "<H1 >", "<H1  >", "<H1   >", and so on

# (atleast w/ one space after H1 is required)

egrep '<H1 +>' regex.txt

# matches "<H>", "<H1>", "<H2>", "<H3>", ... "<H9>"

# (number after "H" is not required)

egrep '<H[0-9]*>' regex.txt

# matches "<H0>", "<H1>", "<H2>", "<H3>", ... "<H9>"

# (number after "H" is required)

egrep '<H[0-9]+>' regex.txt

# matches "o" for atleast once or up to 3

# times ({min,max})

egrep 'co{1,3}l' regex.txt

# matches "o" for exactly 3 times ({min,max})

egrep 'co{3,3}l' regex.txt

# see p 75/780 of "OReilly - Mastering Regular Expressions" book

egrep <HR +SIZE *= *[0-9]+ *> regex.txt

Parentheses and backreferences

        # matches all words that are repeated atleast

# twice (with space between repetitions) like

  - not all `egrep` supports backreference # "the the", "apple apple apple", etc

    and `\< .. \>` egrep '\<([a-zA-Z]+) +\1\>' regex.txt

# same as above but this time this version also

# matches double words with different capitalization

# like "The the"

#

# this seems wrong??

egrep '\<([a-zA-Z]+) +\1\>' regex.txt

Escape sequence

        # removes the special function of "." w/c

# is to match any single character

egrep 'www\.facebook\.com' regex.txt

Miscellaneous

        # moves all non-hidden files on the current directory

# to the target directory

mv *.* Archive/

Some examples

        # matches a variable name that are allowed to contain only

# alphanumeric characters and underscores, but which may

# not begin with a number

egrep '[a-zA-Z_][a-zA-Z_0-9]*' regex.txt

# a string within doublequotes (see book for explanation)

egrep '"[^"]*"' regex.txt

# dollar amount (with optional cents)

egrep '\$[0-9]+(\.[0-9][0-9])?' regex.txt

# time of day, such as "9:17 am" or "12:30 pm"

egrep '(1[012]|[1-9]):[0-5][0-9] (am|pm)' regex.tx

Metacharacters

- special chracters that are used to match and manipulate patterns

^  :  matches start of line

$  :  matches end of line

|  :  provides alternatives

.  :  matches any single character

() :  you can put alternatives inside (separated by |)

?  :  quantifier - optional item (must be placed after the optional item)

*  :  quantifier - similar to ?, matches none, one or more of the immediately-preceding item (exit status is always 0)

+  :  quantifier - similar to ?, MUST match one or more of the immediately-preceding item (exit status is 0 or 1 for fail)

{min,max}  :  interval quantifier - matches the immediately-preceding item for atleast "min" times or until "max" times

Character Class

[]  :  represents a single character to match

Character Class Metacharacter

- these are special characters put inside character classes

- they have different meanings inside a character class compared to when placed outside a character class

-  :  provides range of characters (not considered metacharacter if it is the first character in the class)

^  :  negates the list

Metasequences

- these are used for word boundaries

- use this if you want to search for a particular string that is not embedded in a larger word

- let say you want to look only for the word "cat" and disregard lines with "catleya", "concatenate", etc

- this is not supported on all versions of egrep

\< :  the position at the start of a word

\> :  the position at the end of a word

\1 :  remembers strings/texts inside immediately-preceding parenthesis (used as backreferencing tool)

EGREP

egrep "^(From|Subject): " --> same as egrep "^From: |^Subject: "

- Not all egrep programs are the same. The supported set of metacharacters, as well as their meanings, are often different—see your local documentation

- The useful -i option discounts capitalization during a match

grep -i 'regular_expression' text_file  ##search a filename based on the regular expression

grep -i '^$' text_file  ## searches fro blank lines

grep -i '^$' text_file | wc -l  ## returns the number of blank lines

grep . text_file  ## deletes all blank lines

Thursday, April 29, 2021

SSL Certificates Overview and FAQs

What is SSL?


- Stands for Secure Sockets Layer
- It provides encrypted communciation between two systems

What are SSL certificates?


- This serves as an your website'ss ID
- You can get this from a CA (E.g Verisign, GLobal Sign, etc.)
- In order for the CA to give you an SSL certificate, they will conduct a series
  of checks
  to make sure that you are a legitimate website owner and not an attacker/hacker
- Once given by CA, you need to install this on your web server
- The CA will not give that certificate to anybody except you
- SSL certificates usually is in the form of .crt file (e.g mycompany.crt)

What is public and private keys?


- You can generate your own public and public key (or key pair)
- Your public key can be sent to anyone whose going to relay information to you
- That anyone will encrypt his/her message using the public key you sent
- You can decrypt that message by using your private key
- Private key must be only kept to you
- See "public and private keys.jpg" as an example

What is a CSR?


- It stands for Certificate Signing Request
- It is the one you are going to send to an SSL provider (or CA)
- It is a block of encrypted text that is generated on the server that an SSL
  certificate will be used on
- It contains information that will be included in your certificate such as your
  organization name,
  common name (domain name), locality, and country
- It also contains the public key that will be included in your certificate
- A private key is usually created at the same time that you create the CSR
- The CA will use the CSR you sent to create your SSL certificate
- The certificate created with a particular CSR will only work with the private
  key that was generated with it
- So if you lose the private key, the certificate will no longer work

All about CA trust


Certificate trust works by having a list of trusted CAs inside the client's
device. This device might be a smartphone but usually its a browser like Google
Chrome or Mozilla Firefox.

When you enter a secure website (URL starting in https://), your browser will
check if the website's certificate is signed by one of the trusted CAs on his
list. If yes, then your browser will open the site for you without any warnings.

If no, then it will check if the certificate of the  

source: https://www.sslshopper.com/what-is-a-csr-certificate-signing-request.html

How to create a cerficate chain?

Create a certificate.pem with the following content.

-----BEGIN CERTIFICATE----- 
(Your Primary SSL certificate: your_domain_name.crt) 
-----END CERTIFICATE----- 
-----BEGIN CERTIFICATE----- 
(Your Intermediate certificate: DigiCertCA.crt) 
-----END CERTIFICATE----- 
-----BEGIN CERTIFICATE----- 
(Your Root certificate: TrustedRoot.crt) 
-----END CERTIFICATE-----
Then make sure that if you hit "openssl x509 -in certificate.pem -text"
it will show your domain at the first part instead of the root CA. If
not, try to do the order in reverse.

Wednesday, April 28, 2021

History and General Overview of Cybersecurity

Timeline


<1970 - radios, early computers

1970  - mainframes of campuses became targets

1980  - PCs were invented

1990  - internet

2000  - bluetooth, tablets, smartphones ..

>2000 - international law for computer crimes was established


"Making things easier for hackers is the fact that early network

technologies such as the Internet were never designed with security

as a goal. The goal was the sharing of information."


  * source: pg 53/ CEHv9 (3rd edition) Sybex


Famous hacks through the years


1988 - 1st internet worm was created by Robert T. Morris, Jr.

1994 - Kevin Lee Pulsen took over telephone lines of Kiss-FM to win a Porsche

1999 - David L. Smith created "Melissa" virus w/c email itself to entries

       in user's address book

2001 - Jan de Wit created "Anna Kournikova" virus w/c reads all entries of

       a user's outlook address book

2002 - Gary McKinnon connected to deleted critical US military files

2004 - Adam Botbyl (together w/ 2 other friends) stole credit card information

       from Lowe's hardware chain

2005 - Cameron Lacroix hacked into Paris Hilton's phone

2009 - Kristina Vladimirovna (good looking russian hacker) skimmed around

       3 billion US $ on US banks

mid 2000s - "Stuxnet" virus attacked uranium production

          - "anonymous" group attacked local government networks


Generic examples of Cyber crimes


1.  stealing usernames and passwords

2.  network intrusions

3.  social engineering (involves human interaction)

4.  posting/transmitting of illegal material 

5.  fraud

6.  software piracy

7.  dumpster diving (reconstruction of broken data)

8.  malicious code (viruses)

9.  unauthorized destruction of data

10. embezzlement (form of financial fraud)

11. data-diddling (modification of information to cover up activities)

12. Denial-of-service (overloads a system resource)

13. ransomware (encrypts files on target system to get money)


Devices and Systems that adds security


Software:


- VPNs (Virtual Private Networks)

- IPs (Intrusion Prevention Systems)

- firewalls

- ACLs (Access Control Lists)

- biometrics

- smartcards


Physical security:


- cable locks

- device locks

- alarm systems


Malicious Attacks


- Denial-of-service (DoS)

- manipulation of stock prices

- identity theft

- vandalism

- credit card theft

- piracy

- theft of service


Known hacker groups


Anonymous

https://en.wikipedia.org/wiki/Anonymous_(group)


LulzSec



https://en.wikipedia.org/wiki/LulzSec



Tuesday, April 27, 2021

What are tuples?


- Tuples are another type of sequence in Python
- they are immutable
- they can be packed
- they can be unpacked to variables
- they can contain mutable objects
- lightweight compared to lists

Demo on how to use tuples


        >>> t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')
>>> # Tuples may be nested:
... u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
>>> # Tuples are immutable:
... t[0] = 88888
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> # but they can contain mutable objects:
... v = ([1, 2, 3], [3, 2, 1])
>>> v
([1, 2, 3], [3, 2, 1])

Ways on defining an empty tuple and a tuple with only 1 element


        >>> empty = ()
>>> singleton = 'hello',    # <-- note trailing comma
>>> len(empty)
0
>>> len(singleton)
1
>>> singleton
('hello',)

Packing and unpacking a tuple


        >>> t = 23, 'grapes', 'linux'  # packing a tuple
>>> t
(23, 'grapes', 'linux')
>>>
>>> number, fruit, os = t  # unpacking a tuple
>>> number
23
>>> fruit
'grapes'
>>> os
'linux'
>>>
>>> number, fruit, os, car = t      # number of variables on the left side must match
Traceback (most recent call last):  # the number of elements on the right tuple
  File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 4, got 3)
>>>

Tuples can be converted to list and vice-versa


        >>> secret_message = "hello world"
>>> list(secret_message)
['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
>>> tuple(secret_message)
('h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd')
>>> list(tuple(list(secret_message)))
['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
>>> ''.join(list(tuple(list(secret_message))))
'hello world'

You can also do comparison between tuples


        >>> t1
(1, 5, 7.6)
>>> t2
(2, 8, 100)
>>>
>>> t1 < t2
True
>>>
>>> t1 > t2
False

You cannot delete a specific element in a tuple but you can delete all of them at once


        >>> num = 600, 1, 5, 45.6
>>> num
(600, 1, 5, 45.6)
>>> del num[2]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object doesn't support item deletion
>>> del num
>>> num
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'num' is not defined
>>>

Other operations that can be done on tuples


        >>> len((1, 2, 3))  # length
3
>>> (1, 2, 3) + (4, 5, 6)  # addtion (concatenation)
(1, 2, 3, 4, 5, 6)
>>> ('Hi!',) * 4  # repetition
('Hi!', 'Hi!', 'Hi!', 'Hi!')
>>> 3 in (1, 2, 3)  # membership
True
>>> for x in (1,2,3) : print (x, end = ' ')  # iteration
...
1 2 3 >>>
>>>

Since tuples are also sequences, you can do slice and index operations against them


        >>> T=('C++', 'Java', 'Python')
>>> T[2]
'Python'
>>> T[-2]
'Java'
>>> T[1:]
('Java', 'Python')
>>>

Other tuple functions


        cmp(tuple1, tuple2)
len(tuple)
max(tuple)
min(tuple)
tuple(seq)

Sunday, April 25, 2021

How to be a well rounded Ethical Hacker

Hacking is an engaging field but it is surely not easy. To become a hacker one has to have an attitude and curiosity of learning and adapting new skills.

You must have a deep knowledge of computer systems, programming languages, operating systems and the journey of learning goes on and on.

Some people think that a hacker is always a criminal and do illegal activities but they are wrong. Actually many big companies hire hackers to protect their systems and information and are highly paid. here is the list of most important steps necessary to become a hacker, have a deeper look

LEARN UNIX/LINUX

UNIX/LINUX is an open source operating system which provides better security to computer systems. It was first developed by AT&T in Bell labs and contributed a lot in the world of security. You should install LINUX freely available open source versions on your desktops as without learning UNIX/LINUX, it is not possible to become a hacker. .

CODE IN C LANGUAGE

C programming is the base of learning UNIX/LINUX as this operating system is coded in C programming which makes it the most powerful language as compared to other programming languages. C language was developed by Dennis Ritchie in late 1970’s. To become a hacker you should master C language.

CODE IN MORE THAN ONE PROGRAMMING LANGUAGE

It is important for a person in the hacking field to learn more than one programming. There are many programming languages to learn such as Python, JAVA, C++. Free ebooks, tutorials are easily available online.

LEARN NETWORKING CONCEPTS

Another important and essential step to become a hacker is to be good at networking concepts and understanding how the networks are created. You need to know the differences between different types of networks and must have a clear understanding of TCP/IP and UDP to exploit vulnerabilities (loop holes) in system.

Understanding what LAN, WAN, VPN, Firewall is also important. You must have a clear understanding and use of network tools such as Wireshark, NMAP for packet analyzing, network scanning etc.

LEARN MORE THAN ONE OPERATING SYSTEMS

It is essential for a hacker to learn more than one operating system. There are many other Operating systems apart from Windows, UNIX/LINUX etc. Every system has a loop hole, hacker needs it to exploit it.

LEARN CRYPTOGRAPHY

To become a successful hacker you need to master the art of cryptography. Encryption and Decryption are important skills in hacking. Encryption is widely done in several aspects of information system security in authentication, confidentiality and integrity of data.

Information on a network is in encrypted form such as passwords. While hacking a system, these encrypted codes needs to be broken, which is called decryption.

LEARN MORE AND MORE ABOUT HACKING

Go through various tutorials, ebooks written by experts in the field of hacking. In the field of hacking, learning is never ending because security changes every day with new updates in systems.

EXPERIMENT A LOT

After learning some concepts, sit and practice them. Setup your own lab for experimental purpose. You need a good computer system to start with as some tools may require powerful processor, RAM etc. Keep on Testing and learning until you breach a system.

WRITE VULNERABILITY (LOOP HOLE PROGRAM)

Vulnerability is the weakness, loop hole or open door through which you enter the system. Look for vulnerabilities by scanning the system, network etc. Try to write your own and exploit the system.

CONTINUE NEVER ENDING LEARNING

Learning is the key to success in the world of hacking. Continuous learning and practicing will make you the best hacker. Keep yourself updated about security changes and learn about new ways to exploit systems.

Friday, April 23, 2021

Mounting bitlocker drive in Mac

  1. Install dislocker
brew update
brew install Caskroom/cask/osxfuse
brew install src/dislocker
  1. Insert bitlocker drive to mac
  2. Mount using dislocker
sudo dislocker -v -V /dev/disk2s1 -r -uPASSWORD /tmp/mydrive
sudo hdiutil attach /tmp/mydrive/dislocker-file -imagekey \
     diskimage-class=CRawDiskImage -mountpoint /Volumes/mydrive

Thursday, April 22, 2021

Boolean and Comparison Instructions

AND

  • Performs AND on each bit of source and destination operands
  • Result is stored on destination operand

AND reg,reg
AND reg,mem
AND reg,imm
AND mem,reg
AND mem,imm


  • Example:

mov al,0000001b  ; al = 0000001b
and al,0000000b  ; al = 0000000b


  • Can be used to mask bits (leave them unchanged)

and AL,11110110b    ; clear bits 0 and 3, leave others unchanged


  • Flags being modified:
    • Always clears overflow and carry flags
    • Modifies Sign, Zero, and Parity flags

OR

  • Similar to AND but performs OR instead

OR reg,reg
OR reg,mem
OR reg,imm
OR mem,reg
OR mem,imm


  • Can be used to modify a single bit leaving others unchanged

mov al,00000000b
or al,00000100b   ; set bit 2, leave others unchanged 


  • Here are the flags being modified (assuming AL is being modified)


XOR

  • Can be used as bit flippers (for symmetric encryption) - reversible property


  • Can be used whether a byte has even parity (parity flag set, even numbers of 1’s) or odd parity (parity flag clear, odd numbers of 1’s)

mov al,10110101b  ; 5 bits = odd parity
xor al,0          ; Parity flag clear (odd)
mov al,11001100b  ; 4 bits = even parity
xor al,0          ; Parity flag set (even)


  • Can be also used to check parity of a 16-bit integer - 16-bit parity

mov ax,64C1h ; 0110 0100 1100 0001
xor ah,al    ; Parity flag set (even) 


  • Doing XOR on exactly same integer results to 0 (XOR’ing to yourself). That means that it will set parity flag since the results is all 0’s (even number of 1’s).

mov al,22h   ; al = 22h
xor al,22h   ; al = 0


NOT

  • Inverts bits

NOT reg
NOT mem


  • Doesn’t affect any flags
  • Example:

mov al,11110000b
not al               ; AL = 00001111b


Test

  • Performs an implied AND (doesn’t modify the destination operand)
  • Example:

test al,00001001b     ; test bits 0 and 3


  • Can be used to check if a bit is set (can also work on multiple bits) set - Modifies zero flag



; Example for testing status of a device using but 5
mov al,status

; If bit 5 in status is set, this will clear zero flag.
; Otherwise it will set zero flag.
test al,00100000b
jnz DeviceOffline

; Can be used also on multiple bits 0, 1 and 4
test al,00010011b
jnz InputDataByte


  • Can be used to test if an integer is even or odd

mov eax,18
test eax,1   ; ZF = 1
mov eax,17
test eax,1   ; ZF = 0


CMP

  • Performs implied substraction between source and destination operands (both are not modified)

CMP destination,source


  • Modifies zero, carry and sign flags



  • Example:

; Let’s look at three code fragments showing how flags are affected by the CMP
; instruction. When AX equals 5 and is compared to 10, the Carry flag is set
; because subtracting 10 from 5 requires a borrow
mov ax,5
cmp ax,10 ; ZF = 0 and CF = 1

; Comparing 1000 to 1000 sets the Zero flag because subtracting the source from
; the destination produces zero:
mov ax,1000
mov cx,1000
cmp cx,ax ; ZF = 1 and CF = 0

; Comparing 105 to 0 clears both the Zero and Carry flags because subtracting 0
; from 105 generates a positive, nonzero value
mov si,105
cmp si,0 ; ZF = 0 and CF = 0


Manipulating individual CPU flags

We can manipulate (set or clear) cpu flags using the boolean and comparison instructions. Here are some examples.


  • Zero flag

test al,0   ; set Zero flag
and al,0    ; set Zero flag
or al,1     ; clear Zero flag


  • Sign flag - operates against the highest bit of the destination operand

or al,80h    ; set Sign flag
and al,7Fh   ; clear Sign flag


  • Carry flag

stc   ; set Carry flag
clc   ; clear Carry flag


  • Overflow flag

mov al,7Fh   ; AL = +127
inc al       ; AL = 80h (-128), OF=1
or eax,0     ; clear Overflow flag


How do we mimic conditional statements like in higher level languages?

Here is an example program that finds the large value between 2 integers.


; filename: LargerOfTwoIntegers.asm

mov edx,eax     ; assume EAX is larger
cmp eax,ebx     ; if EAX is >= EBX
jae L1          ; jump to L1
mov edx,ebx     ; else move EBX to EDX
L1:             ; EDX contains the larger integer
  ...

Wednesday, April 21, 2021

Replicated Volume via GlusterFS

In this post, we will demonstrate on how to create a replicated glusterFS
volume. We will use 3 hosts, 2 gluster servers and 1 client all running
Centos 7.3.

vm01 = gluster server 1
vm02 = gluster server 2
vm03 = client

As an introduction, a replicated gluster FS volume ensures that data is present
on all bricks (the building blocks of a volume). This is useful in situations
where you want high-availability and redundancy. There are other types of
gluster FS volumes which you can see at Gluster Volumes.

Configuring the servers


Please note that most of the commands below needs to be ran on both servers
unless the step explicitly tells to run on 1 node only.

1. Install glusterFS server packages on the servers. You have 2 options on
how to install the server packages, one is to install from SIG repository and
the other is from gluster.org. Let's try the first one by searching for the
latest stable repository and installing it.

[root@vm01 ~]# yum search centos-release-gluster
=================================================================================== N/S matched: centos-release-gluster ====================================================================================
centos-release-gluster310.noarch : Gluster 3.10 (Long Term Stable) packages from the CentOS Storage SIG repository
centos-release-gluster312.noarch : Gluster 3.12 (Long Term Stable) packages from the CentOS Storage SIG repository
centos-release-gluster313.noarch : Gluster 3.13 (Short Term Stable) packages from the CentOS Storage SIG repository
centos-release-gluster36.noarch : GlusterFS 3.6 packages from the CentOS Storage SIG repository
centos-release-gluster37.noarch : GlusterFS 3.7 packages from the CentOS Storage SIG repository
centos-release-gluster38.noarch : GlusterFS 3.8 packages from the CentOS Storage SIG repository
centos-release-gluster39.noarch : Gluster 3.9 (Short Term Stable) packages from the CentOS Storage SIG repository


  Name and summary matches only, use "search all" for everything.
[root@vm01 ~]#
[root@vm01 ~]# yum install -y centos-release-gluster310
<output truncated>
root@vm01 ~]#

2. Now that we have a repository to get the packages, let's install the actual
server packages.

[root@vm01 ~]# yum install -y glusterfs glusterfs-cli glusterfs-libs glusterfs-server
<output truncated>
root@vm01 ~]#

3. Start and enable gluster service.

[root@vm01 ~]# systemctl enable --now glusterd
Created symlink from /etc/systemd/system/multi-user.target.wants/glusterd.service to /usr/lib/systemd/system/glusterd.service.
[root@vm01 ~]#

4. Add a separate disk on your nodes to hold our gluster partitions. This make
sure that it is separated from the OS partition to mimic real world setup. Once
added, make sure it can be seen by your hosts. In my case, I added a 5 GB disk
to each gluster server and can be seen as /dev/sdb inside the hosts.

[root@vm01 ~]# fdisk -l | grep sd
Disk /dev/sda: 8589 MB, 8589934592 bytes, 16777216 sectors
/dev/sda1   *        2048     2099199     1048576   83  Linux
/dev/sda2         2099200    16777215     7339008   8e  Linux LVM
Disk /dev/sdb: 5368 MB, 5368709120 bytes, 10485760 sectors
[root@vm01 ~]#

5. Let's now create the underlying filesystem.

[root@vm01 ~]# pvcreate /dev/sdb
  Physical volume "/dev/sdb" successfully created.
[root@vm01 ~]# vgcreate gluster_vg /dev/sdb
  Volume group "gluster_vg" successfully created
[root@vm01 ~]# lvcreate -n gluster_lv -l 100%FREE gluster_vg
  Logical volume "gluster_lv" created.
[root@vm01 ~]# mkfs.xfs /dev/mapper/gluster_vg-gluster_lv
meta-data=/dev/mapper/gluster_vg-gluster_lv isize=512    agcount=4, agsize=327424 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=0, sparse=0
data     =                       bsize=4096   blocks=1309696, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
[root@vm01 ~]#

6. Mount the filesystem and make sure its persistent across reboots.

[root@vm01 ~]# mkdir /brick
[root@vm01 ~]# echo '/dev/mapper/gluster_vg-gluster_lv /brick xfs defaults 0 0' >> /etc/fstab
[root@vm01 ~]# mount -a
[root@vm01 ~]# df -h /brick/
Filesystem                         Size  Used Avail Use% Mounted on
/dev/mapper/gluster_vg-gluster_lv  5.0G   33M  5.0G   1% /brick
[root@vm01 ~]#

7. Open up needed ports - for bricks and pool communication. In versions below
3.4, each brick needs a port starting at 24009/tcp. For versions higher, each
brick needs a port starting at 49152/tcp. Opening this brick ports allows client
to access your volumes. Since we will use 1 brick only, we will open up port
49152/tcp. In addition to that, pool communication on any versions needs to
ports 24007/tcp and 24008/tcp on all servers.

[root@vm01 ~]# firewall-cmd --add-port={24007-24008/tcp,49152/tcp} --permanent
success
[root@vm01 ~]# firewall-cmd --reload
success
[root@vm01 ~]#

8. (Do this on 1 node only). Gluster servers work via Trusted Storage Pool or
"TSP". This pool contains the members sharing the bricks. In order to add a
member, let's execute the command below on the 1st server. Once executed, you
don't need to run it again on the other node.

[root@vm01 ~]# gluster peer probe vm02       
peer probe: success.                                             
[root@vm01 ~]#

9. After being probing for members, let's verify if the pool status.

* from vm01 *

[root@vm01 ~]# gluster peer status
Number of Peers: 1

Hostname: vm02
Uuid: 06525146-da28-4081-b6e3-35372ebf269c
State: Peer in Cluster (Connected)
[root@vm01 ~]#


* from vm02 *

[root@vm02 ~]# gluster peer status
Number of Peers: 1

Hostname: vm01
Uuid: 0c77f8b8-5706-413e-9a25-6e3951d738f5
State: Peer in Cluster (Connected)
[root@vm02 ~]#

10. Create the directory that we will export via a gluster volume

[root@vm01 ~]# mkdir /brick/export1

11. (Do this on 1 node only) Let's create the actual gluster volume and start
it.

[root@vm01 ~]# gluster volume create glustervol01 replica 2 transport tcp vm01:/brick/export1 vm02:/brick/export1
volume create: glustervol01: success: please start the volume to access data
[root@vm01 ~]# gluster volume start glustervol01
volume start: glustervol01: success
[root@vm01 ~]#

12. Let's verify the volume status. Same output should appear on both servers.

[root@vm01 ~]# gluster volume info

Volume Name: glustervol01
Type: Replicate
Volume ID: bf0b27da-ff4b-4bfd-aaa5-1708c16237e1
Status: Started
Snapshot Count: 0
Number of Bricks: 1 x 2 = 2
Transport-type: tcp
Bricks:
Brick1: vm01:/brick/export1
Brick2: vm02:/brick/export1
Options Reconfigured:
transport.address-family: inet
nfs.disable: on
[root@vm01 ~]#

13. Now that our gluster volume "glustervol01" has been setup, let's configure
our client.

Configuring the client


1. Install needed packages to mount the gluster volume

[root@vm03 ~]# yum install -y glusterfs glusterfs-fuse attr
<output truncated>
[root@vm03 ~]#

2. Mount the volume. You may mount the volume from vm01 or vm02.
It doesn't make any difference since this is a shared storage. Take note that
we mount the volume by its volume name "glustervol01" and not by the path of
the brick (/brick/export1).

[root@vm03 ~]# mkdir /mnt/glustervol01
[root@vm03 ~]# mount -t glusterfs vm01:/glustervol01 /mnt/glustervol01
[root@vm03 ~]# touch /mnt/glustervol01/file-from-vm03
[root@vm03 ~]# ll /mnt/glustervol01/file-from-vm03
-rw-r--r--. 1 root root 0 Jan  8 21:50 /mnt/glustervol01/file-from-vm03
[root@vm03 ~]#

3. Client has successfully mounted the volume and can immediately start writing
files to it. Once a file has been created, you will notice that it is present on
the 2 bricks (1 on vm01 and the other on vm02) which signifies a
replicated storage.

* from vm01 *

[root@vm01 ~]# ls -l /brick/export1/
total 0
-rw-r--r--. 2 root root 0 Jan  8 21:50 file-from-vm03
[root@vm01 ~]#


* from vm02 *

[root@vm02 ~]# ls -l /brick/export1/
total 0
-rw-r--r--. 2 root root 0 Jan  8 21:50 file-from-vm03
[root@vm02 ~]#

That concludes our mini tutorial. Hope you enjoy and learn a lot from this.

Tuesday, April 20, 2021

Managing GlusterFS Volumes

Increasing Replicas on Replicated GlusterFS


Let's say existing volume is backed by 2 bricks having a size of 5 GB each

To add 2 more bricks, perform this on 1 node only
gluster volume add-brick my_volume replica 4 node1:/bricks/brick2 node2:/bricks/brick2
"replica 4" means we are increasing the replica count of a file
If we used "replica 2", we will end up in a "distributed-replicated" type of
volume which is not correct if we still want to maintain the volume type as
replicated.

Also, if the sizes of the new bricks are greater then the existing bricks, the
volume size will be the size of the original bricks. The lower size are always
being used so it is better to add bricks with same size of the existing ones.

Expanding a Distributed GlusterFS Volume


1. Perform this on 1 node
   gluster volume add-brick my_volume node1:/brick/brick2
2. The total size of brick(s) will be added on top of the existing size of
   the volume.

Expanding a Replicated GlusterFS Volume


1. Expand the underlying storage on all nodes.
   lvextend -rL +5G /dev/mapper/gluster_vg-gluster_lv
2. The gluster volume size should now be increased by 5G

Monday, April 19, 2021

Tips in recovering Jenkins after unsuccessful upgrade

  1. Backup the following
jobs/
plugins/
config.xml
credentials.xml


  1. Take note of global tools configuration setup
  2. Install new jenkins version
  3. Restore the backups above
  4. Ensure plugins are updated
  5. Ensure global tool configuration is updated

Sunday, April 18, 2021

Running Zenity in Crontab

What is Zenity?


  It is a GNOME application that produces pop-up windows that can be used to send message to user. It also have file selection capabilities by using --file-selection option.

  Example usage are:
  zenity --info # sends a simple pop up message
  zenity --info --text="Backup is running, press OK to close this window"  # with user-defined message


How to run this in CRON?


  Since CRON doesn't process X applications by default, you need to add the following option:
  zenity --info --text="Hi, I was launched via CRON" --display=:0


Sources


http://promberger.info/linux/2009/01/02/running-x-apps-like-zenity-from-crontab-solving-cannot-open-display-problem/

zenity(1)

Saturday, April 17, 2021

Virtual Console Actions on HP Hardwares

1. Momentary Press
  - If server is ON, this action will power OFF the server (simulates graceful shutdown from the OS)
  - If server is OFF, this action will power ON the server

2. Press and Hold
  - When triggered while server is ON, this will force shutdown the server
  - Simulates a physical "press and hold for 6 seconds" on the power switch
  - Useful if OS is not responding to Momentary Press

3. Cold Boot
  - This action will power OFF a running server, waits for 6 seconds and powers it ON
  - You can't use this action when the server is OFF

4. Reset
  - Simulates a reboot from the OS (shutdown -r now)
  - Quickest way to close a frozen program so system may try to recover data and repair software
  - In contrast to "Cold boot", this is referred as "Warm boot"

Friday, April 16, 2021

Useful Ansible Ad-Hoc Commands

FILE/DIRECTORY


# copies a file to multiple severs in parallel
ansible all -m copy -a "src=/tmp/file dest=/tmp/file"

# changes file permission
ansible lab -m file -a "dest=/tmp/file mode=600 owner=bob group=wheel"

# creates a directory
ansible webservers -m file -a "dest=/path/to/c mode=755 owner=root group=mdehaan state=directory"

# deletes a directory
ansible lab -m file -a "dest=/tmp/dir state=absent"

Managing Packages:

# ensures a package is installed (don't update)
ansible lab -m yum -a "name=openssh state=present"

# ensure a package is installed to a specific version
ansible webservers -m yum -a "name=acme-1.5 state=present"

# ensure a package is on the latest version (update if lower version was found)
ansible lab -m yum -a "name=openssh state=latest"

# ensure a package is not installed (uninstalls it if needed)
ansible lab -m yum -a "name=bind state=absent"


Users and Groups


# ensures a this particular user exist
ansible webservers -m user -a "name=apache state=present"

# ensures a this particular user doesn't exist
ansible webservers -m user -a "name=hacker state=absent"


DEPLOYING FROM SOURCE CONTROL


# gets configuration from git
ansible dbservers -m git -a "repo=git://my.db.uk/repo.git dest=/var/lib/db version=HEAD"

Managing Services:

# ensures service is started
ansible webservers -m service -a "name=httpd state=started"

# restarts a service
ansible webservers -m service -a "name=httpd state=restarted"

# ensures a service is stopped
ansible webservers -m service -a "name=httpd state=stopped"


TIME LIMITED OPERATIONS


# executes a long running operation
ansible all -B 3600 -P 0 -a "/usr/bin/long_running_operation --do-stuff"
  * -B 3600 = timeout of 3600 seconds
  * -P 0 = no polling

# checks the status of the long running job
ansible web1.example.com -m async_status -a "jid=488359678239.2844"
  * jid = job id returned when command was ran in the background

# similar to the above but with polling
ansible all -B 1800 -P 60 -a "/usr/bin/long_running_operation --do-stuff"
  * -P 60 = polls every 60 seconds


GATHERING FACTS


# returns the settings of all target hosts
ansible all -m setup


SOURCES


ansible modules:
http://docs.ansible.com/ansible/list_of_all_modules.html

Thursday, April 15, 2021

Linux Command Line Basics

When you first login to a Linux terminal, you are now using bash. Bourne-Again SHell (or BASH) is the default shell. A shell is the interpreter of anything you type on the terminal. In this post, I will briefly discuss the basics of linux command line.

Kinds of Shells

bash
  - Bourne Again SHell
  - based on earlier version of sh
  - commonly default shell in Linux

sh
  - Bourne shell
  - this is were BASH was based
  - not often used in Linux but usually a pointer to /bin/bash

tcsh
  - based on earlier C shell (csh)
  - not popular in Linux

csh
  - the original C Shell
  - not commonly used in Linux
  - very similar to tcsh

ksh
  - combination of features of csh and sh

zsh
  - Z Shell
  - evolution of ksh

How to start a shell?

There are several ways and here are the most common ways.

1. Once you logged in to a linux server (either by SSH or via console), you automatically starts your own shell
2. In xterm or GUI, you can right click on the desktop and open a terminal. In that way, you are also starting a shell

Parts of a shell

Understanding every part of the shell is very important specially for linux administrators because it is the one you interact with everytime you deal with Linux. As an example, when you logged as a regular, the shell will provide you a prompt where you can type your commands.

$ uname
Linux
$

The "$" represents something. In Linux by default, it means that you are logged in as regular user. You may customized it by changing the PS1 environment variable. A root's prompt starts with "#" so its important to clearly distinguished a regular user's prompt from a root's prompt. That can avoid accidentally running destructive command like "rm -fr *" on /. The command used in the example above is "uname" and its output is "Linux". Depending on the command you type, it may return an output or nor. Or it may even return an error.

Types of commands you can use

2 types of commands are "Internal" and "External" commands. Internal are the ones built-in in linux while External are the  ones came from outside sources (e.g came from installing a package). To see what type of command, execute the following:

$ type cd
cd is a shell builtin
$ type date
date is /bin/date
$
$ type -a pwd
pwd is a shell builtin
pwd is /bin/pwd
$

The first example tells us that "cd" is an Internal command while the second one indicates that "date" is an external command. There are some commands you may encounter that has both Internal and External versions. So to see it, add "-a" on type command as shown in the 3rd example above.

Getting help

Since we are dealing with command line, we often need more information on a particular command we are using. There are several ways on how to display command information.

1. Using "man" - perhaps the most important help utility in Linux
  man <command>  # displays man pages of a command
  man -k <string>  # searches the man database for commands (or description) matching the specified string
  man -K <string>  # similar as above but do a full search (takes significantly longer to complete)
  man <section number> <command/config file>  # prints information on a specific manual section (see discussion below)

Man contains sections which groups the type of information you can see on a particular command. Not all command have the same manual sections. Here are the example of manual sections:

Section Number
  1 -- user commands (contains traditional command usage and options)
  2 -- system calls provided by the kernel (not commonly used by sys ads)
  3 -- library calls
  4 -- device files
  5 -- file formats (these are config files like "man 5 fstab")
  6 -- games
  7 -- miscellaneous
  8 -- system administration commands (usually ones that must be run as root)
  9 -- kernel routines

On the 9 manual sections, only 1, 5, and 8 are the most commonly used by system administrators.

2. Using pinfo/info - not all commands support this
  info coreutils 'ls invocation'  # as an example, you can see this command under "SEE ALSO" of ls (1)

3. Exploring /usr/share/doc
  - some packages includes README files under this directory
  - you can see examples here
  - sometimes there are also sample configurations

Environment Variables

These are global values read by the shell and inherited by the user (which can also be overriden) during startup. To see all environment variables, type "env". Here are the common environment variables in Linux.

PS1 - this is your prompt (e.g [user@host] $)
HOME - contains path to your home directory
HOSTNAME - the hostname of current machine where you are logged in
LOGNAME - the username used to login to the machine

To display the values, use the following command:

echo $HOME

Wednesday, April 14, 2021

Systemd Mounts

INTRODUCTION


Aside from managing services, systemd can also handle filesystem mounts similar to /etc/fstab. In this post, I
will show you how to mount local and remote filesystems using systemd.

MOUNTING A LOCAL FILESYSTEM


1. Create your .mount unit file
cat << EOF >> /etc/systemd/system/test.mount  # unit filename must match the mountpoint
[Unit]
Description=test mount

[Mount]
What=/dev/mapper/test_vg-test_lv
Where=/test  # this mountpoint must match the name of the unit file
                     # if this directory doesn't exist, systemd will create it with 0755 permissions

[Install]
WantedBy=multi-user.target  # if we want to mount the fs on boot, add this Install section
EOF
systemctl daemon-reload
systemctl start test.mount
systemctl enable test.mount  # this mounts filesystem at startup


2. Validate mount
[root@server ~]# df /test
Filesystem                  1K-blocks  Used Available Use% Mounted on
/dev/mapper/test_vg-test_lv   1041060 32944   1008116   4% /test

[root@server ~]#


Now that you have mounted a filesystem using systemd, you can unmount it by "systemctl stop test.mount"
or still by traditional way of "umount /test". The latter will automatically stop test.mount. If the mountpoint
is as series of directory tree (e.g /test/sub1), change the unit filename to test-sub1.mount and update
the Where= option.

MOUNTING A REMOTE FILESYSTEM


In the previous part, we used a local filesystem. Now let's try using a CIFS share to mount using systemd.

1. Create your .mount unit file
cat << EOF >> /etc/systemd/system/cifs.mount
[Unit]
Description=test mount (CIFS)

[Mount]
What=//192.168.122.11/share
Where=/cifs
Options=credentials=/root/cifscreds  # you can specify here mount options

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl start cifs.mount
systemctl enable cifs.mount


2. Validate mount
[root@server ~]# df /cifs
Filesystem            1K-blocks  Used Available Use% Mounted on
//192.168.122.11/share   1041060 32944   1008116   4% /cifs
[root@server ~]#


SOURCES

Man pages:
systemd.mount(5) - contains basice usage and options

Tuesday, April 13, 2021

Git Tutorial

Introduction


In this post, I will share to you some of the basic commands and concepts revolving around GIT.

If you have experience in git and you want to skip, you can go directly to "Examples" section.

Workflow

Here are the trees maintained by git:

Working Directory -> Index (Add) -> Head (Commit)

working dir = holds actual files
index = staging area
head = contains last commit you made

Commands


# repository commands
git clone https://github.com/username/hello-world.git # clones a remote repo
git clone username@host:/path/to/repository # same as above but using ssh keys
git remote -v # prints remote branches

# configs
cat .git/config

# adding/removing files/directories to index
git add filename # adds a single file
git add fileA fileB ... fileN # adds multiple files
git add * # adds all files and directories (except empty directories)
git add dir/* # adds dir and its contents (dir must be non-empty)
git reset file # unstages a file

# commiting changes
git commit -m "description of change you've done" # short way
git commit # long-way (that will bring you to a VI editor)

# pushing changes
git push # push all changes to repo (regardless on what branch you are)

# branching
git branch # lists all branches
git branch branch_name # creates a branch*
git checkout branch_name # switches to another branch
git push origin branch_name # push branch to repo**
* when you create a branch, that new branch will also contain all files and directories on the
the current branch where you are located. So if you create a branch from a branch with no files,
expect that the new branch will also have no contents!
** you cna push a branch even you are not currently located at that branch

# history and logging
git blame <path to file> # prints all changes on a file line by line
git log # prints all commits

Examples


Here are practical examples to get you going instead of blowing your mind with lots of
commands.

Cloning a remote repository w/o SSH keys:
git clone https://github.com/batman31/myproject
* cloning a remote remote clones also the branches associated with it

Cloning a respository w/ SSH keys:
* first, generate SSH key pair *
* second, upload the public key to github (usually its in the settings menu where you can add one) *
git clone git@github.com:zeon31/hello-world.git

Deleting a file from localdisk and remote git repo:
git rm octopus.txt # to delete multiples files, you can ise wildcards like `git rm file*`
git commit -m "deleted octopus.txt"
git push

How to delete a directory and its contents?
git rm pets/*
git commit -m "pesky pets"
git push

Creating a branch and submitting a pull/merge request:
* given that your local repo is up-to-date *
git branch fix-bug
git checkout fix-bug
* do you code change on the file you want to change ... *
* go to git hub: project > merge requests > create one > merge*

I have so many untracked files and I want to remove all of them
git clean -fd
* -f = force
* -d = include directories

How to delete a branch in 2 steps
1. delete local branch: git branch -d <branch name>
2. delete remote branch: git push origin --delete <branch name>

Restoring a deleted file
git checkout $(git rev-list -n 1 HEAD -- "$file")^ -- "$file"

Sources


A simple nice guide with illustrations
http://rogerdudler.github.io/git-guide/

Another nice tutorial allowing users to enter commands on the web page
https://try.github.io/

Monday, April 12, 2021

Moving user to a new home directory



This is a simple hack if you want to move an existing user's home directory to a new location. This is helpful if you have a new partition create for user's home dirs (e.g /home2)

1. Execute this 1 command
usermod -md /home2/bob bob
# /home2 must exist
# /home2/bob will be created automatically by the command
# bob's files on the old home dir will be moved to the new
# the old home dir (together with its contents) will be deleted


2. Test as root
su - bob
# this shouldn't return an error

3. You can also see that the /etc/passwd entry has been updated as well
grep bob /etc/passwd

Sunday, April 11, 2021

Conditional Structures

Example 1 - Simple conditional

Pseudocode:


if( op1 == op2 )
{
  X = 1; 
  Y = 2;
} 


Assembly code:


  mov eax,op1
  cmp eax,op2
  jne L1
  mov X,1
  mov Y,2 
L1:
  ...


Example 2 - NTFS

Pseudocode:


    clusterSize = 8192;
    if terrabytes < 16
      clusterSize = 4096;


Assembly code:


  mov clusterSize,8192 
  cmp terrabytes, 16
  jae next
  mov clusterSize,4096 
next:
  ...


Example 3 - If Else

Pseudocode:


if op1 > op2
  call Routine1
else
  call Routine2
end if 


Assembly code:


  mov  eax,op1
  cmp  eax,op2
  jg   A1
  call Routine2
  jmp  A2
A1:
  call Routine1
A2:
  ...


Example 4 - nested If Else

Pseudocode:


if op1 == op2
  if X > Y
    call Routine1
  else
    call Routine2
  end if
else
  call Routine3
end if 


Assembly code:


  mov eax,op1 
  cmp eax,op2
  jne L2
  call Routine3
  mov eax,X
  cmp eax,Y
  jg L1
  call Routine2
  jmp L3 
L1:
  call Routine1
  jmp L3
L2:
  call Routine3 
L3:
  ...

Saturday, April 10, 2021

Writer interface does opposite of reader interface.








Function signature is similar to reader interface.





IO Copy




Example:

io.Copy(os.Stdout, resp.Body)


resp.Body - implements Reader interface (source)

os.Stdout - implements Writer interface (destination)





Friday, April 9, 2021

Installing ClusterSSH in Windows

You need to install Cygwin first. Cygwin provides Linux functionality on Windows-based machines.

PART 1: Installing Cygwin


NOTE:
  - During this setup, it will allow you to manually install the tools you need like ssh-server and perl. Cygwin has no package manager (like rpm, yum, dpkg, etc..) so if you want to install additional packages, you need to run the setup again and choose "Install from Internet (downloaded files will be kep for future re-use)"
  - Make sure you also have an internet connection

1. Download the latest version at: https://cygwin.com/setup-x86.exe
2. Run the downloaded file
3. Choose "Install from Internet (downloaded files will be kep for future re-use)"
4. Root Directory: C:\cygwin
5. Install: All Users (RECOMMENDED)
6. Local Package Directory: C:\Users\merrell\Desktop
7. Direct Connection
8. Choose A Download Site: This is where you will get the packages you want to install. Usually I choose the first one.
9. Select Packages: You can now select the packages you want. Download time will depend how large the packages you are downloading. Since we will install clusterssh, we need to choose the following packages:
perl
make
gcc-core
perl-tk
perl-Test-Pod
perl-Test-Pod-Coverage
perl-Try_Tiny
perl-File-Slurp
perl-File-Which
perl-Readonly
xinit
openssh
curl
wget
10. Once finished, you can now open the Cygwin terminal on which you can run Linux commands

PART 2: Installing clusterssh


NOTE:
  - You need a live internet connection before proceeding on the steps below

2. Extract the file anywhere you want
3. Open Cygwin terminal and go to the extracted folder
4. Open XWin server: Programs > Cygwin-x (32-bit) > XWin server
5. In Cygwin terminal, execute the following commands in order to install cssh and all required modules:
  $ cpan
    * press enter to all questions *
    cpan[1]> install Module::Build
    cpan[2]> exit
  $ perl Build installdeps
    * press enter to all questions *
  $ perl Build.PL
  $ ./Build
  $ ./Build test
  $ ./Build install
6. Now test cssh by opening 2 terminal at once using "root" as user
  $ cssh -l root host1 host2