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

Thursday, April 8, 2021

MRepo tutorial

WHAT IS MREPO?


  It is an open-source tool that creates a repository out of an ISO file (usually your installation disc) or from
public URLs like http://mirror.centos.org/. Those are some of the possible sources, explore the docs (see
sources below this post) for more choices.

  Aside from creating a repository, mrepo has the capability of making sure that both sides are in sync. When
a package from a http://mirror.centos.org/centos-7/7/os/x86_64/Packages/ has been remove, your local
repository will be udpated when you launch the mrepo command with the appropriate options (see tutorials
below on how to use mrepo command). Or if a newer package is available, mrepo will download it for you
and add it to your local repo.

INSTALLATION


1. Download the tarball from the site below. On other distribution, this is available via RPM on EPEL.
http://dag.wieers.com/home-made/mrepo/mrepo-0.8.7.tar.bz2

2. Untar it to any place you want.
tar xvf mrepo-0.8.7.tar.bz2

3. Go to the extracted directory and install it
cd mrepo-0.8.7
make install
# the installation will also produce a sysV script since this tool was prior to systemd. You may convert
# it to a unit file.

TIP: You might want to keep the extracted directory because it contains useful information like sample
    configurations and tutorials

CREATING A REPOSITORY FROM AN ISO FILE


In this part, we will create a repository out of an ISO file which typically is your distribution's installation disc.

1. Make sure the required directory exists
mkdir /var/mrepo


2. Create a subdirectory for your distribution
mkdir /var/mrepo/centos7-x86_64
# I chose the subdirectory name centos7-x86_64 because it is a valid format which is $dist-$arch.
# $dist and $arch is part of the config file as you will see in step 4. You may also use a format of $dist
# only but the former has an advantage in terms of containing the packages. If you use $dist only and
# in the future you provided URLs as source of your repository together with an existing ISO source,
# mrepo will create another directory which is /var/mrepo/$dist-$arch and put RPMs there instead on
# /var/mrepo/$dist. So in result, you will have 2 directories under /var/mrepo, subdir $dist which contain
# the actual ISO file and $dist-$arch which contains the RPMs from the URLs. So to make things cleaner,
# just create /var/mrepo/$dist-$arch at the start which will contain both the ISO and the URL RPMs w/o
# forcing mrepo to create separate directories.


3. Copy your distribution's ISO file (installation disc) to that directory
cp CentOS-7-x86_64-DVD-1611.iso /var/mrepo/centos7-x86_64/


4. Update the main config file, mrepo.conf, by appending the configurations below
cat << EOF >> /etc/mrepo.conf
[centos7]  # $dist or tag; part of subdirectory name in step 2
name = Centos 7 (64-bit) # mrepo doesn't care any description you put here
release = 7
arch = x86_64  # self explanatory? :) this is also part of subdirectory name in step 2
metadata = repomd  # we'll pick this as we are creating an RPM repository (another possible value is apt)
iso = CentOS-7-x86_64-DVD-1611.iso  # must match the filename copied in step 3
# it is important that you specify the filename correctly because mrepo will look for that file
EOF


TIP: You may also create a separate .conf file under /etc/mrepo.conf.d/ and mrepo will read it as if it is
included in the main config

5. Create the repository
mrepo -ugv  # see mrepo -h for flag uses
# As a summary, that command will perform the following:
#  1. Create /var/www/mrepo/$disr-$arch directory tree
#  2. Look for ISO files under the specified directories in order
#      /var/mrepo/$dist-$arch/$iso
#      /var/mrepo/$tag/$iso
#      /var/mrepo/iso/$iso
#      /var/mrepo/$iso
#  3. Mount ISO file to /var/www/mrepo/$dist-$arch/disc1 as a loop device
#  4. Create the links under /var/www/mrepo/$dist-$arch/


TIP: To see the detailed steps on how it create the repository, you may increase verbosity by -vvvvv (5 Vs!)

6. Once the above command completes, you will expect a directory structure similar to mine:

[root@home ~]# ll /var/www/mrepo/centos7-x86_64/  # this is the /var/www/mrepo/$dist-$arch
total 266
drwxr-xr-x. 8 root root   2048 Dec  5 21:20 disc1  # mountpoint of iso under /var/mrepo/$dist/$iso
lrwxrwxrwx. 1 root root     50 Mar 29 20:24 HEADER.shtml -> ../../../../usr/share/mrepo/html/HEADER.repo.shtml
drwxr-xr-x. 2 root root     42 Mar 29 20:24 iso  # contains a symlink to /var/mrepo/$dist/$iso
lrwxrwxrwx. 1 root root     50 Mar 29 20:24 README.shtml -> ../../../../usr/share/mrepo/html/README.repo.shtml
drwxr-xr-x. 2 root root      6 Mar 29 20:24 RPMS.all  # empty
drwxr-xr-x. 3 root root 212992 Mar 29 20:24 RPMS.os  # contains the actual RPMs as well as the repodata that came from the iso file
[root@home ~]#


7. You have now created a repository out from your ISO. But that repository is not yet available to clients
    until you share it via any methods like http, ftp, or nfs. Please see the other part of this post on where
    I demonstrate to you on how to share the repository via http method.

CREATING REPOSITORIES FROM URLS


In this part, we are going to create and sync a local repository from a public URL repository. As an example, http://mirror.centos.org/centos/7/extras/x86_64/, contains extra packages for Centos 7 so we will use that for this demonstration.

1. Update the mrepo.conf and add the following lines:
cat << EOF >> /etc/mrepo.conf
[centos7]
name = Centos 7 (64-bit)
release = 7
arch = x86_64
metadata = repomd
base = http://mirror.centos.org/centos/$release/os/$arch/
updates = http://mirror.centos.org/centos/$release/updates/$arch/
extras = http://mirror.centos.org/centos/$release/extras/$arch/
epel = https://mirrors.fedoraproject.org/metalink?repo=epel-7&arch=$arch
EOF
# base, updates, extras, and epel are strings to describe the corresponding URL repository
# the following directory trees will be created:
#  /var/mrepo/$dist-$arch/{base,updates,extras,epel}
#  /var/www/mrepo/$dist-$arch/RPMS.{base,updates,extras,epel}


2. Install lftp because mrepo will use that to get packages from the URLs
yum install -y lftp


3. Sync the repositories. Since this is the first time, this will download al packages. All succeeding sync using
mrepo command will just download new packages or remove packages in your local that are no longer existing from the URLs.
mrepo -ugv


4. When you are finish downloading all packages, you can now make the repositories accessible to clients.
    See next section for the steps.

NOTE: If you can use "mirrorlists" in traditional yum repo, here in mrepo you cannot.

Making your repositories accessible via HTTP

There are many ways on how you can make your repositories accessible. Some of this are via
NFS and FTP. We will use HTTP for this demonstration since this is by far the most common way.

* On server *

1. Install http
yum install -y httpd


2. Start and enable at boot
RHEL 6.X/sysV systems:
service httpd start
chkconfig httpd on
RHEL 7.X/systemd systems:
systemctl start httpd
systemctl enable httpd


3. Open up port 80 on firewall
IPTABLES:
iptables -A INPUT -m state --state NEW -p tcp --dport 80 -j ACCEPT
service iptables restart
FIREWALLD:
firewall-cmd --add-service=http --permanent
firewall-cmd --reload


4. Add link of each repo to DocumentRoot. You may use another approach but this is the easiest for me. :)
ln -s /var/www/mrepo/ /var/www/html/mrepo


5. If selinux is enabled and in enforcing mode, change selinux context of /var/mrepo to allow httpd access
semanage fcontext -at httpd_sys_content_t '/var/mrepo(./*)?'
restorecon -Rv /var/mrepo


6. Make sure your repository is accessible by testing it on your local browser.
http://localhost/mrepo/centos7-x86_64/RPMS.base

* On client *

1. Create .repo file
cat << EOF >> /etc/yum.repos.d/server.repo
[base]
name=Centos 7 - Base Packages (64-bit)
baseurl=http://server/mrepo/centos7-x86_64/RPMS.base
EOF


2. See if you can see the repository
yum repolist all


3. Validate by installing a package
yum install -y zsh


SOURCES


Official site:
http://dag.wiee.rs/home-made/mrepo/

mrepo command usage (no manual page but this is sufficient):
mrepo -h

Documentations:
mrepo-0.8.7/docs

Sample configurations:
mrepo-0.8.7/configs

Other web turorial:
https://asenjo.nl/wiki/index.php/Mrepo_centos7