startup process:

After powerup, m/c goes thru different steps before the login prompt appears. A lot of useful info here: https://www.thegeekstuff.com/2011/02/linux-boot-process

and here: https://www.tldp.org/LDP/sag/html/boot-process.html

and here: https://www.linuxnix.com/linux-booting-process-explained/

and here: https://wiki.archlinux.org/index.php/Arch_boot_process

and here: http://tldp.org/LDP/khg/HyperNews/get/tour/tour.html

In short these are the steps:


1. Powerup: As soon as the power button is pressed, the system powers up. CPU is released off reset. 80x86 CPU puts addr 0xFFFF0 on Addr lines, and this is the very first addr that the CPU will read from. This addr (historically) happens to be the addr on EEPROM (a separate chip on motherboard, that just stores read only memory. EE stands for Electrically Erasable and Programmable. We use EEPROM instead of ROM so that manufacturers can push out updates easily). This 0xFFFF0 addr contains another addr to which the CPU jumps to (known as indirection). EEPROM stores piece of code starting from that addr. That code is known as BIOS/UEFI or boot firmware code (UEFI is referred to as BIOS or UEFI BIOS, even though UEFI is different than BIOS). There are still 12 more bytes at addr 0xFFFF4 and beyond. We may store soft power up (i.e reset or warm boot) addr at that location, and likewise at other top addr. That way, we may jump to some other addr in ROM code depending on the powerup scenario. 

A. BIOS/UEFI: This is the code stored in EEPROM. On older system, BIOS used to be stored here. On newer computers, UEFI is stored instead of BIOS. UEFI is just different code than BIOS.

BIOS/UEFI consist of 2 parts. The 1st part is stored in EEPROM. This part does similar things for BIOS/UEFI in initializing the system.The 2nd part is stored on Hard disk or some other disk. The 2nd part is called the 1st stage boot loader.

For BIOS systems, BIOS code first does POST (power on self test). It then initializes the remaining hardware, detects the connected peripherals (mouse, keyboard, pendrive etc.) and checks if all connected devices are healthy. You might remember it as a 'beep' that desktops used to make after POST is successful. Finally, the firmware code cycles through all storage devices and looks for a boot-loader. These storage device may be floppy disk, hard drive, usb stick, etc. It will then choose a disk drive and read it's very first sector, which is addr 0x7C00. This is called boot sector on floppy disks. On hard disk, it's called master boot record (MBR), since HD can have several partitions, each with it's own boot sector. MBR is the 1st 512 bytes on the HD. The code in MBR then transfers control to other code, which does the main booting.

For UEFI systems, UEFI code first initializes hardware to the point it can detect keyboard keys pressed, display something on screen, and access the EFI partitions of detected drives. EFI partition is a separate partition for UEFI booting. So, the 1st part of UEFI code stored on EEPROM also contains a file system driver to read that EFI partition as only then it can actually load EFI extensions from there. EFI partition is like a 1st stage boot loader.

These boot loaders (either on MBR or EFI partition) are called 1st stage boot loader.

Difference b/w BIOS and UEFI: This link explains it nicely: https://www.freecodecamp.org/news/uefi-vs-bios/

BIOS: BIOS stands for Basic Input Output system. In short, BIOS is stored in EEPROM and all of the BIOS related code is in this memory. It runs in 16 bit mode, so that's why it doesn't any graphic support, and we have to use use arrow and enter keys to navigate thru the options. It is the screen that shows up when you press F1, F2 or some other key (depending on your laptop manufacturer) on computer startup.

UEFI: UEFI stands for Unified Extensible Firmware Interface. It does the same job as a BIOS, but with one basic difference: it stores all data about initialization and startup in an .efi file, instead of storing it on the firmware. This .efi file is stored on a special partition called EFI System Partition (ESP) on the hard disk. This ESP partition also contains the bootloader. UEFI was designed to overcome many limitations of the old BIOS such as drive size, slow boot time, etc. UEFI is fast and it runs in 32/64 bit mode (that's why it has GUI). All modern systems support UEFI, so if you bought a laptop in the last 5 years, you most certainly have UEFI on it.

Secure boot: One of the most important feature added by UEFI is a security feature called "Secure Boot", which prevents the computer from booting from unauthorized/unsigned applications. This helps in preventing rootkits, but also hampers dual-booting, as it treats other OS as unsigned applications. Currently, only Windows and Ubuntu are signed OS. This is a a big pain when installing any Linux OS. One way to get around is to disable "Secure Boot" feature (see in Linux Installation section).

B. MBR/GPT: After code in EEPROM runs, control is transferred to MBR (for BIOS startup) or to EFI partition (for UEFI). These usually reside on hard disk (see in Filesystems section for details on hard dik, partitions, etc)

MBR (Master Boot Record): It is the first 512 bytes on hard drive (first 446 bytes is code, remaining 64 bytes is partition info. read more about MBR in File systems section). First BIOS executes code in MBR, then identifies bootable partition (on that hard disk), reads boot sector of that partition, and then starts the code in that boot sector. This code (in boot sector of that partition) reads in the kernel from the partition and starts it. Ideally, the kernel image is stored in seq addr, and the code can be read sequentially. However, this would require a separate partition for kernel image, which is not practical. Instead the kernel image is stored in a File system (FS), so the code will need to figure out the sectors where the FS has stored this kernel image. In a FS, image may be scattered on different physical sectors, so there's no requirement of kernel image to be in consecutive locations. The most common way to achieve this is using a bootLoader as GRUB or LILO.

GPT (GUID Partition Table): MBR is only 512 bytes which is too small. So, a newer scheme called GPT was introduced. It is a standard for the layout of the partition table on a physical hard disk, using globally unique identifiers (GUID). Usually, MBR and BIOS (MBR + BIOS), and GPT and UEFI (GPT + UEFI) go hand in hand. This is compulsory for some systems (eg Windows), while optional for others (eg Linux). UEFI supports the traditional MBR too, while BIOS may support modern GPT too.

3. GRUB: GRUB is a bootloader pgm used in Linux world. grub is now replaced by grub2 as of 2020 in all new linux distro. grub2 was written from scratch and is in bash. grub files are not found anymore on any linux distro, so we'll be talking about grub2 (even though we may write grub, we mean grub2 unless mentioned specifically)

For systems still using classical BIOS on powerup,  Grub replaces the code in MBR (1st 512 bytes) with it's own code. This is done by any Linux installer without you doing anything. So, when system is powered up in BIOS mode, and code in MBR is executed, it's the GRUB bootloader code that gets executed (instead of default code in MBR that was there before grub replaced it, which was windows code). For systems using UEFI, grub is copied on to EFI partition (again it's done by any Linux installer without you doing anything.). Grub is read directly from an EFI System Partition. GRUB has the advantage of being able to read ext2, ext3, and ext4 partitions and load its configuration file. Grub uses hd for hard disk, instead of sd used by Linux File System.

 
GRUB for BIOS:

Grub for BIOS is slightly different than Grub for UEFI. Grub for BIOS is not really used in any system after 2020, so you can skip the section below.

Grub for BIOS intro here: https://www.dedoimedo.com/computers/grub.html

Grub (for BIOS) works in 2 stages.This 2 stage approach allows large code in GRUB to be executed w/o the limitation of 512 bytes in MBR.

  • 1st stage: This is located in the MBR and mainly points to Stage 2, since the MBR is too small to contain all of the needed data.  
  • 2nd stage: This points to its configuration file, which contains all of the complex user interface and options we are normally familiar with when talking about GRUB. Stage 2 can be located anywhere on the disk. If Stage 2 cannot find its configuration table, GRUB will cease the boot sequence and present the user with a command line for manual configuration.  

If we do auto install of any linux distro, GRUB gets installed by default. To manually install it, we need to first log into a linux OS, and from within there, execute grub cmd to get a grub prompt. Next we need to place GRUB Stage 1 in the first sector of the hard disk (MBR or Partition Table). For this, we first find all possible grub on the system (there may be more than 1 grub if more than 1linux distro is installed). Then we choose the one which we want to be copied to MBR.

  • grub> find /boot/grub/stage1 => this will possibly return (hd0,1) for SUSE, (hd1,2) for Ubuntu, etc (assuming system has multiple linux OS installed). That means it found stage 1 grub in these partitions.
  • grub> root (hd1,2) => This is saying that choose grub from disk1 (2nd disk) and partition 2 (3rd partition in 2nd disk) to copy to MBR.
  • grub> setup (hd0) => Write above grub stage 1 from (hd1,2) to hd0 (disk 1 MBR)
  • grub> quit

Instead of above 4 step process, we can just use single cmd shown stating where to cp grub stage1 to => grub-install /dev/hd0 => Here we cp grub from one of the available grub stage1 to hd0 MBR

GRUB files are in 2 main dir => /boot/grub and /usr/lib/grub.

  • /boot/grub/ => GRUB cfg (or menu) is located on the root partition. For legacy grub, we have menu.lst file, while for grub2, we have grub.cfg.
    •  Legacy grub has /boot/grub/menu.lst. menu.lst lists all partitions and marks the active one. It lists partition one by one, Format is:
      • 1st partiton is windows OS and is marked as active. Since this OS is not understood by GRUB, chainloader is used.
        • title Windows 95/98/NT/2000 => title says what OS it is (for human understanding)
        • rootnoverify (hd0,0) => This specifies the root (/) partition of Windows. In this instance, the boot image is on (hd0,0) => hd0 means 1st hard disk, and later 0 means 1st partition on that disk. rootnoverify implies GRUB cannot understand Windows OS, i.e. no multi-boot compliance. The job of mounting the boot image is left to chainloader (see below). 
        • makeactive => this sets the active partition to this partiton, i.e (hd0,0)
        • chainloader +1 => This feature is used for OS such as Windows that cannot be booted directly. They are booted by the method of chainloading (GRUB passes the control of the boot sequence to another bootloader, located on the device to which the menu entry points).
      • 2nd partition is Linux OS
        • title Linux => implies it's Linux OS
        • root (hd0,1) => root specifies where the root (/) partition is. Here / is on (hd0,1), i.e hard disk 0, partition 1.
        • kernel /vmlinuz root=/dev/hda3 ro
    • grub2 has /boot/grub/grub.cfg. This is autogenerated at install via grub-mkconfig using templates from /etc/grub.d and settings from /etc/default/grub
      • /etc/grub.d/ => It has separate files for each OS entry in grub menu (options that we see to choose the OS when grub is loaded), i.e 00_header, 10_linux, 20_memtestx86+,40_custom, etc. 40_custom
  • /usr/lib/grub/ => It has stage1 and stage2 files under /usr/lib/grub/i386-pc/. In grub2, you see *.mod files here, as they are all modules for various things as grub,  boot, sleep, etc.

GRUB for EFI:

GRUB cfg file for EFI are in /boot/efi/EFI/<linux_OS_name>/grub.conf

This grub.cfg is a very small wrapper which takes us back to /boot/grub/grub.cfg.

If we have multiple Linux Os installed, then every time we install a new OS, it's GRUB will overwrite the prior GRUB in MBR/GPT. So, we won't be able to access other Linux OS, as the latest Linux OS only sees itself and Windows (assuming Windows is there). To prevent this, we don't allow later Linux OS to install GRUB (don't do auto install Linux OS, but instead choose "manual installation" and then turn off "grub installation"). This way, we leave the GRUB untouched from prior Linux OS installation.

User Selection for OS:

Once the second stage boot loader (from chosen partition in BIOS or EFI partition in UEFI) is in memory, it presents the user with a graphical screen showing the different operating systems or kernels it has been configured to boot (when you update the kernel, the boot loader configuration file is updated automatically). On this screen a user can use the arrow keys to choose which operating system or kernel they wish to boot and press Enter. If no key is pressed, the boot loader loads the default selection after a configurable period of time has passed. Depending on what OS user chose to load, it loads Windows or Linux or any other OS listed in the menu. Assuming Linux is selected, it locates the corresponding kernel binary in the /boot/ directory. The kernel binary is named using the following format — /boot/vmlinuz-<kernel-version> file (where <kernel-version> corresponds to the kernel version specified in the boot loader's settings). On Ubuntu, file is /boot/vmlinuz-3.10.0* (single file, size~7MB, there is also a rescue copy of this with same size),
 
The boot loader then places one or more appropriate initramfs images into memory. The initramfs is used by the kernel to load drivers and modules necessary to boot the system. Once the kernel and the initramfs image(s) are loaded into memory, the boot loader hands control of the boot process to the kernel. Boot loaders only need to support the file system on which kernel and initramfs reside (the file system on which /boot is located). 
 

 

4A. Kernel load: First Kernel is loaded into RAM and remains there until shutdown. 

The very first part of the Linux kernel is written in 8086 assembly language (boot/bootsect.S). When run, it moves itself to absolute address 0x90000, loads the next 2 kBytes of code from the boot device to address 0x90200, and the rest of the kernel to address 0x10000. The message ``Loading...'' is displayed during system load. Control is then passed to the code in boot/Setup.S, another real-mode assembly source.

The setup portion identifies some features of the host system and the type of vga board. If requested to, it asks the user to choose the video mode for the console. It then moves the whole system from address 0x10000 to address 0x1000, enters protected mode and jumps to the rest of the system (at 0x1000).

4B. Kernel decompress: The Linux kernel is installed compressed, so it will first uncompress itself. The beginning of the kernel image contains a small program that does this. The code at 0x1000 comes from zBoot/head.S which initializes registers and invokes decompress_kernel(), which in turn is made up of zBoot/inflate.c, zBoot/unzip.c and zBoot/misc.c. The decompressed data goes to address 0x100000 (1 Meg = 2^20), and this is the main reason why Linux can't run with less than 2 megs ram.

Decompressed code is executed, and eventually, the routine start_kernel is invoked. start_kernel executes a wide range of initialization functions., including unpacking the initramfs (initial RAM filesystem), which becomes the initial root filesystem. The purpose of the initramfs is to bootstrap the system to the point where it can access the root filesystem.

The source for the above operations is in boot/head.S. start_kernel() resides in init/main.c, and never returns. Anything from now on is coded in C language, left aside interrupt management and system call enter/leave. The kernel then executes init as the first process. The early userspace starts. Until this point, initial root filesystem in RAM was being used. At the final stage of early userspace, the real root is mounted ((i.e sets up / root dir, and all dir under it), which replaces the initial root filesystem. This is done via a call to pivot_root ( ) which unmounts the temporary root file system and replaces it with the use of the real one. The memory used by the temporary root file system is then reclaimed. If the mounting of the root filesystem fails, for example because you didn't remember to include the corresponding filesystem driver in the kernel, the kernel panics and halts the system.


5. Init: Once real file system is mounted, kernel finishes it's own part of boot process. init process then tries to execute /sbin/init which is the first user pgm with process id=1. The first process it runs is a script at /etc/rc.d/rc.sysinit which check all the system properties, hardware, display, SElinux, load kernel modules, file system check, file system mounting etc.Then initrd (initial ram disk) is run. Now, /etc/inittab file is read to determine run level, and pgms for that run level are run. Once all these pgms for that run level have run, init process runs one more file /etc/rc.local which are the last commands run in initialization process or even booting process. Once everything is completed the control is given back to the kernel.

On newer systems using systemd, init is replaced by systemd. So, 1st user pgm with process id=1 is systemd (and NOT init) in such a case. See details under "init vs systemd" section.

After exec()ing the init program above, the kernel has no direct control on the program flow. Its role, from now on is to provide processes with system calls, as well as servicing asynchronous events (such as hardware interrupts). Multitasking has been setup, and it is now init which manages multiuser access by fork()ing system daemons and login processes.


6. Prompt: init (or systemd) forks 2 processes: getty (get terminal) and login (for user login). These allow the user to log into the system.

A. getty: getty is called once for each virtual terminal (typically six of them), which initializes each tty and brings up a "login:" prompt asking for a username. Without this getty pgm, communication via terminal can't happen. The init program starts up other programs similar to getty for networked connections. For example, sshd, telnetd, and rlogind are started to service logins via ssh, telnet, and rlogin, respectively. Instead of being tied directly to a specific, physical terminal or modem line, these programs connect users' shells to pseudo ttys. These are devices that emulate terminals over network connections. getty listens at the terminal and waits for the user to notify that he is ready to login in (this usually means that the user must type something). When it notices a user, getty outputs a welcome message (stored in /etc/issue), and prompts for the username. On my CentOS laptop, /etc/issue has these 2 lines: \S, \r, \m are prompt variable char, and print corresponding system info. i.e \u=user, \h=hostname, etc.

ex: /etc/issue => this has 2 lines shown as below (On ubuntu, it just has a single line with name of linux distro "Ubuntu 22.04.2 LTS \n")

\S

Kernel \r on an \m

Above 2 lines print this message followed by the "login:" prompt

CentOS Linux 7

Kernel 3.18xxx on an x86_64

DESKTOP-ASHISH login:

Now this prompt for login may be CLI or GUI. If we did a basic installation of Linux with no graphical interface, then we will see CLI on all virtual terminals. Else if X11 was installed, then getty starts display manager (dm) on one of these virtual terminal (the default virtual terminal) which brings a graphical login screen (you will see a gdm pgm running, under user "root"). Once the username is provided, getty pgm disappears. But before it disappears, it starts a login pgm at /bin/login to complete the login process.

B.login: login pgm gets the username as a parameter from getty pgm, and prompts the user for the password. It checks them against /etc/passwd and /etc/shadow.

Even though the file/etc/passwd is supposed to store encrypted passwords too (which it used to do in old days), but this file is readable by everyone. So, now for security reasons, the encrypted password is stored as "x" in this file, and the real encrypted password is stored in /etc/shadow file which is readable by super user (su) only. So, even encrypted password is not visible to any one else besides su.

On successful matching of username/password, the login program begins a session for the user by setting environment variables and starting the user's shell, based on /etc/passwd.

/etc/password file contains one line for each user of the system. That line specifies, among other things, the login name, home directory, and program to start up when that user logs in. There are seven entries on each line separated by colon. Exact syntax of this file explained here: https://www.cyberciti.biz/faq/understanding-etcpasswd-file-format/

The last bit of information (the program to start up) is stored after the last colon of each line. If nothing follows the last colon, the standard shell /usr/bin/sh is assumed by default. The following lines show typical lines from my /etc/passwd file

  • root:x:0:0:root:/root:/bin/bash => thi is when we type "root" at login prompt, login shell started is bash for root user
  • gdm:x:42:42::/var/lib/gdm:/sbin/nologin => in RHEL, every process runs under a particular user. Users corresponding to certain processess dont have the need to login. So, they have been assigned with a nologin shell. 
  • ashish:x:1000:1000:ashish:/home/ashish:/bin/bash => this is the line used when user "ashish" logs in. After password match, bash shell is started. NOTE: we don't have to start a shell. We could run any program, i.e :/home/my_test.tcl is an equally valid program that can be mentioned here, and login pgm will start that pgm instead of a shell.

The blinking cursor that appears when typing password in CLI is the login program running. No shell has been started yet.


7. login: The login program displays the contents of /etc/motd (message of the day) after a successful login, and then it executes the pgm mentioned in /etc/passwd, which is usually a shell pgm. This is called a login shell. This login shells may be one of many shells supported, and is the entry in /etc/passwd file as indicated above. The default shell on most linux distro is bash. Once the user's login shell is started, it will typically run a runtime configuration file, such as .bashrc or .cshrc, before presenting a prompt to the user. For bash shell, /etc/profile; is executed. in addition, it executes .profile in the user's home directory. For csh, .login is executed. However, if the login was done graphically via dm, then different set of runtime configuration files are called to call the graphical windows i/f. However, on other virtual terminals (accessible by pressing ctrl+alt+F2 or ctrl+alt+F3 or so on), we still see the text login shell after entering username and password.


8. xinit:  For grahical windows i/f, login pgm calls some other configuration files after successful login.These runtime configuration file will call startx or xinit. It runs the user's xinitrc runtime configuration file, which normally starts a window manager (wm). When the user is finished and exits the window manager, xinit, startx, the shell, and login will terminate in that order, returning to getty. NOTE: xinit may not be use any longer on linux distro that have switched to systemd (instesd of init).

startx: This cmd is a wrapper to xinit, and is implemented differently on diff OS variants. More details here: https://www.computerhope.com/unix/startx.htm. startx is a standalone cmd and is used to start the wm under full user control. This is not the cmd that is used by the OS to start wm, but whatever "xinit" script is being used by the OS achieves results similar to this.


 

steps to download and run programs in Linux = Using Package Manager:

Once linux is installed and running, you will want to download and install new software on your system. One way to install any new software on your computer is to download source code from internet, then compile it on local machine using Makefile provided, then install it in appropriate dir. This process is very cumbersome, and is suitable for advanced users only. However for layman users, this process can all be automated by using package managers that come preinstalled on linux OS. However for these pacakage managers to be able to download, compile and install the software, the software needs to be in a package in a special format. The creator of the software should provide their software in specific format for that package manager, or else the package manager can't be used. Fortunately, most of the software that you will ever encounter is available in multiple package formats, so they can be used with almost all package managers.

Package Manager:

A package manager or package management system is a collection of software tools that automates the process of installing, upgrading, configuring, and removing computer programs for an OS on a system. A package manager deals with packages which are distributions of software and data in archive files. Packages contain metadata, such as the software's name, description of its purpose, version number, vendor, checksum, and a list of computer_programming dependencies necessary for the software to run properly. Package managers are designed to eliminate the need for manual installs and updates. Running any package manager requires admin rights, so you have to precede cmds with "sudo" (see in "linux cmds" section for more details on sudo).

Following are the package managers and package formats supported by various linux distro. As you can see there are only 2 formats that will suffice all linux users - .deb and .rpm formats.

1. Deb (Debian) format: All Debian and its derivatives such as Ubuntu, Linux Mint, support .deb package format. The package manager is apt (advanced package tool). APT resolves dependency problems and retrieves requested packages from designated package repositories. APT delegates the actual installation and removal of packages to dpkg. So, instead of directly typing dpkg cmds, APT handles it for us. We type apt commands on command line to interact with APT. NOTE: APT is different than apt cmd line tools. There are various apt cmd line tools to interact with APT pkg mgr. Some examples of cmd line tools are apt-get, apt-cache, aptitude, apt, etc. Until 2016, we had apt-get and apt-cache as 2 most popular cmd line tools for APT. However, cmd line tool "apt" was introduced in Ubuntu 16.04, to combine cmds from both of these into one, and make cmds simpler. apt is now recommended cmd to use with APT. You will still see lots of documentation for apt-get and apt-cache online, and you can continue to use them (as they will still work), but apt is the path forward. So, I'll just show "apt" cmds from now on.

Few of the important apt cmds here: https://itsfoss.com/apt-command-guide/

  • sudo apt update => updates the pkg database repository, so that APT knows if there are any newer packages available, for software already installed on your system. You will see pkg info being retrieved from various servers. You need to run this cmd, before installing any new pkg, so that you get the latest in the repo.
  • sudo apt upgrade => once the pkg database is updated using above cmd, we can upgrade all installed pkg with this cmd. If update cmd not run before upgrade, then APT repository may not that there are latest updates available, and will say, it's up to date.
  • apt search php => this is neat way to find out or search for any packages which contains the specified term, here it searches for any pkg containing term "php" in it. It will generally show hundreds of pkg with that name, so it's usually hard to determine which pkg to choose. i.e if we see 100's of pkg with name "php", we don't know which one to download. Some of these are basic pkg, while some are additional modules for that pkg, etc. Usually search on internet will show what all to download. NOTE: no sudo reqd, as it doesn't make any changes to your system.
  • apt show php => will show additional info about pkg "php". Useful to know, before you install that pkg.
  • sudo apt install <pkg_name> => most used cmd. installs required pkg, like apache2, tcl, etc
  • sudo apt remove <pkg_name> =>removes the pkg.

These are some important directories associated with APT:

/etc/apt has the apt configuration folders and files. All files/folders in /etc/apt are:

  • sources.list: Locations to fetch packages from. This has path to locate the desired packages, which might be available on the network or a removable storage medium, for example, and retrieve them, and also obtain information about available (but not installed) packages.  On my system, this file has 1 line as follows:
    • #deb cdrom:[Linux Mint 19 _Tara_ - Release amd64 20180717]/ bionic contrib main non-free => This line is commented out. So, apt automatically searches other files in sources.list.d for location of packages:
  • sources.list.d/official-package-repositories.list => This has the location of where to fetch packages from:
    • deb http://packages.linuxmint.com tara main upstream import backport => We see many more links from ubuntu, canonical, etc.
  • To use official debian repository which contains about 50K packages, we could insert a line like this in any of above file, and then run "apt update"
    • deb http://ftp.debian.org/debian stable main contrib non-free => Now, APT will use this link to download stable pkg
  •  apt.conf.d => APT configuration file fragments.
  • preferences: version preferences file. This is where you would specify a preference to get certain packages from a separate source or from a different version of a distribution

/var/cache/apt/archives/: storage area for retrieved package files. It has all .deb files that are downloaded. deb files are readable text files. This is a good place to see what was downloaded for let's say "sql" package.

/var/lib/apt/lists/: storage area for state information for each package resource specified in sources.list

Ex: to install a new scripting language called tcl (which is not installed by default on Linux Mint), we run these cmds from any dir in a terminal:

sudo apt install tcl => sudo needed to run as super user since root permissions are needed to run apt. It asks for user's password, and then shows what's going to get installed, and asks if you want to continue. On pressing Y, it downloads pkg. shows lines like this ...

Get:1 http://archive.ubuntu.com/ubuntu bionic/main amd64 libtcl8.6 amd64 8.6.8+dfsg-3 [881 kB] => download link for tcl pkg

Preparing to unpack .../libtcl8.6_8.6.8+dfsg-3_amd64.deb ... => .deb file for tcl downloaded from link above,
Unpacking libtcl8.6:amd64 (8.6.8+dfsg-3) ... =>

Setting up tcl8.6 (8.6.8+dfsg-3) ... => This finally installs tcl on your m/c.

NOTE: Instead of using command line above, Linux Mint provides graphical software called "synaptics package manager" and "software manager". We can use this too to install new software just by searching for that and clicking "install". However if any of these is open, and you try to run apt cmd on cmd line in terminal, you may get a lock error. So, close these before using cmd line i/f on terminal.

 

2. RPM (Red Hat package manager) format: All Fedora and it's derivatives as CentOS, RHEL, and SUSE, OpenSUSE support .rpm package format. RPM is delivered as a single file either as .src.rpm (for source pkg) or as .<arch>.rpm(for binary pkg). Package manager is yum.

Yum (yellowdog Updater Modified). Few of the imp cmds:

  • sudo yum update => updates the pkg database repository, so that yum knows if there are any newer packages available, for software already installed on your system. -y option updates w/o asking for your confirmation. Similar to apt, you need to run this cmd, before installing any new pkg, so that you get the latest in the repo.
  • sudo yum upgrade => once the pkg database is updated, we can upgrade all installed pkg with this cmd. 
  • sudo yum upgrade httpd -y =>this upgrades specific pkg named "httpd". -y upgrades w/o asking for confirmation
  • yum search httpd => searches for any pkg containing term "httpd" in it
  • yum info httpd => shows additional info about pkg "httpd".
  • sudo yum install <pkg_name> => most used cmd. installs required pkg, like apache2, tcl, etc
  • sudo yum remove <pkg_name> =>removes the pkg. This will figure out all files associated with that pkg, and cleanly remove them. Linux "rm" cmd should NOT be used to remove packages.

 ex: upgrading firefox:

  1. sudo yum update => updates local repo.
  2. sudo yum info firefox => This gives info on installed firefox pkg, as well as the latest one available. For me, it was showing intalled firefox version as 80.xx, while available was showing as 93.0.0. That meant my pkg was out of date. However, for latest avilable pkg to show, we should have run above "update" cmd, else yum will show latest based on when the repo was last updated.
  3. sudo yum upgrade firefox => This finally upgrades firefox to latest 93.0.0

On top of individual pkg, there are also groups, of which there are 2 kinds:

1. environment groups: consists of a group of packages define how the server needs to be built, it can be Web Server, Minimal installation or server with the graphical interface.

2. groups: consists of all other groups of software like “Development Tools” or “System Administration Tools”. We can apply yum to these groups too

  • yum groups => prints summary of groups. On my centOS laptop, it shows 12 Environment groups and 25 groups.
  • yum grouplist => prints all avilable groups with group names. Env groups are Cinnamon Desktop, Mate Desktop, Basic Web Server, etc. Groups are Cinnamon, Mate, Sound and Video, etc.
  • yum groupinfo "Cinnamon Desktop" => provides more info about this DE (Desktop Env) pkg. 
  • sudo yum groupinstall "GNOME desktop" => installs GNOME3 DE
  • sudo yum groupremove "Security Tools" => removes this group named "security tools"

FIXME: yum details FIXME

Raspberry Pi:

Very useful tool to learning microcontrollers and building projects. This is preferred over all other microcontrollers, as it can support Linux OS, so you can write programs in any programming language, and be able to control pins. It works just like working on a desktop or laptop with Linux installed. The advantage that Raspberry Board provides is that it behaves as a microcontroller, so it has pins available that you can use to drive any output or to receive any input which allows you to connect various devices to it's pins and make cool projects. A regular microprocessor doesn't provide you these general purpose pins (known as GPIO), so we can't use processors from Intel/AMD to make these projects.

official website: https://www.raspberrypi.org

Generations of Raspberry pi:

A summary of Raspberry pi journey is on wiki here: https://en.wikipedia.org/wiki/Raspberry_Pi

More and more powerful raspberry pi are coming on market. What started as 1st generation Raspberry pi 1 in 2012, soon expanded to Raspberry Pi 2, Pi Zero, Pi 3 and now Pi 4 as of 2020. All Raspberry Pi have Broadcom SOC which have ARM microprocessor. Here are the details:

Pi 1:  It came out with Model B in 2012, then a cheaper Model A. Then improved pi Models B+ and A+ were released. Broadcom BCM2835 SOC was used in these 1st gen Pi, which had 700MHz ARM 11 Processor. Models A/B had 256MB memory, while A+/B+ had 512MB memory. The ARM11 is the same CPU used in the original iPhone although at a higher clock rate and mated with a much faster GPU. So, you can imagine the power of Pi 1, and this is the lowest performing 1st gen Pi !!

Pi 2: These were released in 2015. They initially had BCM2836 SOC which featured a 900 MHz 32-bit quad-core ARM Cortex-A7 processor with 1 GB RAM. Later versions had BCM2837 SOC which featured a 1.2 GHz 64 bit quad-core ARM Cortex-A53 processor.

Pi Zero and Pi Zero W: These were cheapest pi and smaller in size. Pi Zero was released in Nov, 2015 for $5. In 2017, Pi Zero W was released, which was similar as Pi Zero but with wifi and bluetooth capabilities (the term W implied Wireless). This sold for $10. Both used the same Broadcom BCM2835 SoC as the first generation Raspberry Pi, although now running at 1 GHz CPU clock speed. They both had 512MB memory. With wireless capabilities added, Pi Zero W was the first real all purpose microcontroller. With a rock bottom price of $10, and working as a desktop, there was nothing on market that could compete with it. I myself bought couple of Pi Zero W for $3.14. They work extremely well, although slow for any browser viewing.

Pi 3: There were 3 versions: B, A+ and B+. All used BCM2837 SOC. Model B was released in 2016 with BCM2837 SOC which featured a 1.2 GHz 64-bit quad-core ARM Cortex-A53 processor (same as Pi 2). B/B+ had 1GB memory, while A+ had 512MB memory. Model B+ and A+ had higher CPU speed of 1.4GHz. However, now all Pi had wireless capabilities, That was the only meaningful addition over Pi 2.

Pi 4: The only model released here as of 2020 is Model B which was released in 2019. It used BCM2711 with a 1.5 GHz 64-bit quad-core  ARM Cortex-A72 processor. More details in next section.

For the 1st time, Pi supported ARM virtualisation capabilities. It came in 4 flavors, with RAM of 1GB, 2GB, 4GB and 8GB.  It added USB type C port for powering the board. It had 2 micro HDMI ports for connecting 2 4K monitors. It also has 2 USB 2.0 ports and 2 USB 3.0 ports.  There was significant upgrade in RAM, comparable to low end PC, for the first time. Pi 4 with 8GB RAM became a full desktop capable processor, which can perform on same level as Intel or AMD machines.

Where to Buy:

Raspberry Pi is sold at bunch of places (the website lists such places), but the prices vary a lot. You can usually buy raspberry pi at discount during sale. In USA, Microcenter is the best place to buy, as they frequently have lowest performing Raspberry Pi Zero W for $3.14 (i.e value of pi). BestBuy also has sales some of the times. Best website to look for such deals is slickdeals.net, and search for raspberry.

Which Raspberry Pi to Buy:

I would suggest sticking to Raspberry Pi Zero W, or Raspberry Pi 4. All other Raspberry Pi are basically just variations of these 2. My next sections will only deal with these 2 flavors of Pi. Pi Zero W is the cheapest Raspberry Pi, and could be had for $3. Raspberry Pi 4 with 4GB memory could be had for $40. It is so powerful that it can serve as a full desktop replacement. I've a 2GB version, and though it works well, it lags in browsing. 8GB is where all programs can fit in memory well, even with multiple tabs open on browser. So, 8GB would be ideal, though 4GB will serve well for 99% of tasks.

You don't need to buy any accessories bundled with Pi, since they are a lot cheaper to buy separately. You will need to buy below accesories, before you can use Pi. However, I don't suggest buying Keyboard/Mouse and Monitor, as we'll use vnc to connect to raspberry pi. That way we can use our laptop's keyboard and monitor to work on raspberry pi.

- memory SD card => Get a SD card of 64GB or 128GB as these are very cheap and go for $10 or less. Large size is good, incase you need to install a lot of stuff on raspberry pi later.

- USB cable => You may order some cheap USB cables from ebay

- Keyboard/Mouse => You don't need to buy this.

- Monitor => You don't need to buy this.

Raspebrry Pi: Getting started

Steps to get a raspberry project going. I'm listing general steps irrespective of which raspberry Pi you use. My preferred raspberry Pi are Pi Zero W (since it's the cheapest one), and Pi 4 (since it's the most powerful one).

A. Burn Raspberry Pi OS on SD card: I'm doing this on a Laptop which has Linux Mint installed on it. The below steps are all done on the laptop, and NOT on raspberry board.

1. download he raspberry pi OS:

https://www.raspberrypi.org/downloads/raspbian/

Download the "Raspbian Buster with desktop and recommended software". Download the zip file, and extract it. It gets extracted as "2020-02-13-raspbian-buster-full.img".

2. get a SD memory card with atleast 8GB space as raspbian OS after extraction needs atleast 8GB. On a terminal, type the lsblk cmd to check what what devices it shows connected (After inserting the SD card)

$ lsblk -p
NAME             MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
/dev/sda           8:0    0 931.5G  0 disk
├─/dev/sda1        8:1    0   260M  0 part /boot/efi
├─/dev/sda2        8:2    0    16M  0 part
├─/dev/sda3        8:3    0 246.7G  0 part
├─/dev/sda4        8:4    0   980M  0 part
├─/dev/sda5        8:5    0   7.5G  0 part [SWAP]
└─/dev/sda6        8:6    0 676.1G  0 part /
/dev/sr0          11:0    1  1024M  0 rom  
/dev/mmcblk0     179:0    0  29.7G  0 disk
└─/dev/mmcblk0p1 179:1    0  29.7G  0 part /media/ash/6636-6330

Above o/p of lsblk cmd shows our SD memory card as mmcblk0. It has 1 partition mmcblk0p1 which is mounted on /media/ash/6636-6330. We need to unmount the device by typing below cmd.

$ umount /dev/mmcblk0p1 => NOTE: we unmount the partition in SD card, and not the SD card device itself (i.e unmount mmcblk0p1 and NOT mmcblk0)

3. Now copy the raspbian image on to SD memory card using Linux dd cmd below:

$ sudo dd bs=4M if=2020-02-13-raspbian-buster-full.img of=/dev/mmcblk0 status=progress conv=fsync => block size is set to 4MB to speed up copy time, while status is set so that copy progress can be seen
[sudo] password for anvay:
7319060480 bytes (7.3 GB, 6.8 GiB) copied, 222 s, 33.0 MB/s
1746+0 records in
1746+0 records out
7323254784 bytes (7.3 GB, 6.8 GiB) copied, 249.04 s, 29.4 MB/s

4. Now once the image is copied on SD card, eject the SD card, and it's time to insert that card in Raspberry pi motherboard.

B. Power up Raspberry Pi: Now, get your Raspeberry Pi Board out, and perform all below steps on it:

1. Insert The memory card into the card slot on Raspberry pi board.

2. Get the accessroies needed for raspberry Pi. At the least you need a usb Type A or Type C cable for powering the raspberry pi. For initial setup, you will also need a monitor and a keyboard and mouse.

3. There is no turn on/off button on any raspberry pi. They start powering up, as soon as the usb cable is connected to a power supply. You will see a raspberry logo, and then the screen should appear. You should connect it to your wireless network, by clicking on wireless icon on top right. That wireless network name and password will be stored, so you don't need to enter it ever again.

At this stage you are done with basic setup, and can start using your Pi to browse, write scripts, play games or do nothing.

Other Utilities:

There are few other things that we can install on raspberry pi, that will be useful.

C. ssh: To connect to raspberry pi terminal, you could use ssh. Look into "openssh" section of "software tools". First we need to install ssh on raspberry pi. NOTE: client ssh is always installed by default. It's the sshd daemon or server ssh that is not installed (or not activated) by default, as it's not needed that often.  ssh is already installed on raspberry pi, it just needs to be enabled. This link shows how: https://www.raspberrypi.org/documentation/remote-access/ssh/

Our laptop from which we are trying to connect to raspberry pi only needs the client ssh, and NOT the server ssh. Since client ssh is slways installed by default, we don't need to install server ssh (i.e sshd), but it's always good to install it on the laptop too, as that way we can connect to our laptop from raspberry pi too (the use case is rare though).

Once all that is done, we need to find the ip address of raspberry pi. You can also use the name of "raspberry pi". By default, name of your raspberry pi is "raspberrypi" and it's private ip address is of form 192.168.1.xx. You could run cmd ifconfig and get the ip address of your ethernet i/f or wireless i/f. But in our case, it's not needed. We know the name of our device, and that will suffice. Next, we also need to know he username on raspberry pi. By default, username is "pi". So, to connect to raspberry pi, we need to go to our laptop from where we want to connect to raspberry pi. Assuming it's a Linux laptop, open a terminal and type ssh cmd as below:

ssh pi@raspberrypi => This will ask for your password on raspberry pi for user "pi". On successful connection, it will show raspberry pi terminal. The terminal prompt will change to that of raspberry pi prompt. By default, the new prompt will show as "pi@raspberrypi".

Now you can access any file, open apps , etc. NOTE: not all application will open from this terminal due to Xdisplay not setup. Look in Xwindows section on how to do it.

D. scp: If you want to copu any file from raspberry pi to your laptop or from your laptop to raspberry pi, you use this cmd. Usage is provided on "openssh" section. From your local computer, type this cmd to transfer files back and forth. NOTE: in both examples below, we ssh into raspberry pi, that's why we need server ssh (sshd) running on raspberry pi.

ex: scp test1.py pi@raspberrypi:/home/ramesh/. => copies test1.py from local computer to raspberry pi

ex: scp pi@raspberrypi:test3.txt project/tmp/tmp.txt => copies test3.txt from raspberry pi to our local computer in current dir subdir as tmp.txt

 E. Setup VNC:   Now we'll connect VNC. This is the last thing that will allow us to use our raspberry pi as a local desktop without requiring monitors, mouse, etc. VNC steps are detailed in vnc section. Once you have vnc installed on raspberry pi, connect to it using any laptop running windows or Linux. There in nothing special or different for raspberry pi. You need to have vnc server installed on raspberry pi, and vnc client installed on your laptop from which you are going to connect to raspberry pi.

 

 

 

 

Linux Mint:

Best one is Linux Mint with least issues during installation. I would recommend this over any other OS (except CentOS which is my favorite), as everything works flawlessly. For beginners who are used to Windows, Linux Mint might be more comfortable to use than CentOS, as the user interface is very similar to Windows.

Installating OS:

Download, install using these links:

https://itsfoss.com/guide-install-linux-mint-16-dual-boot-windows/

The only deviation from steps in link above, is that you will be asked if you want internet connection enabled to allow 3rd party software to be installed. You can choose "no" and not install any 3rd party software, as you can always install it later when needed. I have chosen "yes" too, and that has worked fine. Also, choose just 2 partitions, a "/" partition, and a small "swap" partition (no need for a separate "home" partition). Once you click on "Install now", you will see 2 partitions (ext4 and swap). Click "OK", and it will start installing Linux. It will take a while (shown by progress bar, usually 30 minutes). Click "restart now" at end, and it will now start showing GRUB menu. It shows "Linux mint", "windows" as well as few other options. You can choose "Linux Mint" or "windows" depending on which OS you want to start.

steps:

1. Download LinuxMint ISO:

 I downloaded "Linux Mint 19, Cinnamon 64-bit" edition. Follow link below to get Linux mint.

 https://linuxmint.com/download.php

As of Sept 2021, Latest one is Linux Mint 20. It has 3 variations - Cinnamon, Mate and Xfce. The only difference is in the GUI, otherwise they are all similar. If you don't know which one to install, choose "Cinnamon" as it's most popular.

2. Copy ISO files to USB drive:

You need linux already installed in order to copy the iso to usb from within linux. We don't use UUI to burn the iso as explained previously. Use cp cmd as explained under installation.

1A. Use cp cmd to copy to usb drive

sudo cp /home/aarav/Downloads/LinuxMint-20.2-cinnamon-64bit.iso /dev/sdb => Do not use /dev/sdb1. See in "Linux Installation section for details"

3. Reboot Windows:

Once copied, plug it in windows laptop and reboot it. Do not use UUI, as it gives error. You will be greeted with "Install LinuxMint" screen. Follow prompts as explained in link above from itsfoss

 

Useful Customization:

Adding application pgm icons to panel:

To add to panel (bottom most bar on your laptop is called panel), goto Menu-> serach for that application, and then right click when it shows up. Now you will options for "add to panel" and "add to desktop". click on "add to panel", and you will see the icon added to bottom panel.

 

Installing other software:

Here are links for few more pgms to install. Firefox and Skype are the important ones. Luckily they install flawlessly.

Install Firefox browser:

Most websites, with exception of very few, open fine in firefox in Linux Mint. Video/audio on internet sites work as well. Firefox is installed by default. If not install, type these cmds on Terminal.

firefox -version => shows version of firefox installed. If it's not installed or not latest one, run below cmds

sudo yum install firefox => installs firefox

sudo yum update firefox => This updates firefox to latest version

firefox -version => shows version of firefox installed

Install Skype:

Installing skype is very easy on LinuxMint. Skype binaries for linux are now available from skype website. Follow these steps to install skype:

  1. sudo apt update
  2. Download skype binary. 2 ways:
    1. download skype binary (.deb pkg) directly from skype site: https://www.skype.com/en/get-skype/. Choose "Get Skype for Linux deb"
    2. wget cmd: install wget (if not installed and then use it to download skype)
      1. sudo apt install -y wget
      2. type this cmd on linux terminal to download it: wget https://repo.skype.com/latest/skypeforlinux-64.deb
  3. sudo apt install ./skypeforlinux-64.deb => NOTE: ./ is needed else you get an error that deb file not found. provide appr path for downloaded .deb pkg, if you are not running this cmd in the dir where you downloaded this deb pkg. Linux will ask for root passwd, and then install skype.

 

CSS - cascading style sheet

CSS  are very important to know. They provide a central location to control the physical appearance of your website. You create a single css file and put definitions to define how elements are to be displayed on all of the pages of your website. Other big advantage is that you can control the layout of your whole website through this css file. Before CSS, the only way I knew to control the layout of a page, was by coding the whole page as a big table, with several nested tables inside it, to make complicated layouts. However, CSS greatly eases this by having a div command, that does this work for you. Below, I'll start with various CSS commands.

comments indicated as /* comments */

CSS syntax:

CSS is made up of rules. A CSS rule is made up of a selector and a semicolon-separated list of declarations inside brackets. Each declaration has a property and a value separated by a colon. If an element in an associated HTML document matches a selector in the style sheet, then the declarations will be applied to that element.

selector {property1: value1; property2:value2; } /* This whole thing is called a CSS rule.  Everything inside { ... } is called a declaration, which can have multiple property:value pairs
selector is html element/tag or something else defined.
property is the attribute
value is the value assigned to the attribute.

ex: center aligned paragraph with black text color and arial font. Now, any p element in html doc, will use these values to display the text. Everything can be on a single line, since CSS, like HTML ignores spaces.
p{
text-align: center;
color:black;
font-family: arial;
}

ex: assign green color to h1, h2 and h3 tags. Now, any ph1,h2,h3 element in html doc, will display the text in green color.
h1,h2,h3 {color: green}

Inheritance:  One of the key properties of CSS is that styles are inherited down the document tree, i.e if a property is specified for body, all elements in document tree of body (i.e p tags, etc) will inherit this property.

CSS implementation:

CSS can be implemented in 4 ways:
1. inside html elements: you can apply it directly to individual elements with the style attribute. This is called inline style. This is doCSS implementation:ne inside html document, and is not really in the CSS format that we talked above. This is because style is an html attribute.

style attribute: specify the styling of an element, like color, font, size etc. Can be used with almost any tag. Format is style="property:value;"  where property/value are CSS property/value. However, since using style attribute in html document has a very localized effect, it's least efficient way of applying CSS, and used rarely, only to fix bugs or cross-browser issues.

<p style="color:red">This is a red paragraph.</p> => specifies text color as red
<body style="background-color:powderblue;"> ..... </body> => everthing within body tag has background clor as blue
<h1 style="border:2px solid Tomato;">Hello World</h1> => This puts a border of 2pixels around the text and assigns red color to it
<h1 style="font-size:60px;">Heading 1</h1> => specifies font-size as 60 pixels. font-size can also be in %, i.e 150%
<h1 style="font-family:verdana;">This is a heading</h1> => specifies font as verdana
<p style="text-align:center;">Centered paragraph.</p> => defines horizontal text alignment in that para


2. inside html page: In this implementation, style element is used. <style> is a tag (or element) just like other elements in html. This is also called internal style sheet. Rules in a <style> element apply to everything in that page, so it is more efficient. <style> elemnt is usally put in the head section of html, but browsers will obey the style even if put in the body section.

ex: <style> p { color: red; } </style>

3. in external css file: This should be the preferred way, especially if the style is applied to many pages. Above style element applies rules only to the page they are in, but this applies to all the pages, where this file in referenced.The <link> element references an external style sheet. It's put in the head section.
<link href="/styles.css" rel="style sheet">

The file styles.css would then contain the CSS code only. The same CSS file can be used for multiple pages, so browser download styles.css file only once saving on bandwidth and page rendering speed.
p { color: red; }

4. link from within existing file: The final way to include CSS is to link from within existing CSS . This requires that some CSS has already been included, via a link or a <style> element:
<style> @import url('styles.css'); </style> /* here style sheet is imported from the head section of the document.

Other CSS selectors:

So far, we saw type selectors, where the selector consists of the element name and selects a type of element for the property to be applied to. But there are many other CSS selectors as well, which are more helpful. We'll see 3 css selectors => Element name selector(we saw this above), Id selector (chooses element based on id attribute) and class selector (chooses element based on class attribute)

id selector: An ID selector chooses an element based on the id attribute. An ID selector consists of a hash character (#) followed by the id. Property is applied to element with matching id. Only one element can have a given id. So, ID selector by itself is not very helpful, as it requires adding an unique id attribute to every element that we want the property to be applied to. In case we want to use the same property to be applied to more than one element, we use class selector explained later.

ex: here we define myelement id, and apply it to p element in html file.

#myelement { => this CSS section may be in head of html file or separate css file.
color: white;
background-color: black;
}

<p id="myelement">A paragraph</p> => This is in body of html file. Here p element has an id=myelement. No other element can have this id. Above selector applies color and background-color to this p element as it has matching id. All ohter p elements are left intact, if they don't have this id.

ex:  #green {color: green} => matches any element that has an id attr with a value of green. It sets attribute "color" to green for all those matching elements.

ex:  p#para1{text-align:center} => matches any "p" element that has id with value of para1. Thus we are more specific here that the attribute can only be applied to "p" element and not to any other element.

class selector: The class selector chooses elements based on the class attribute. Unlike the id attribute, values in the class attribute don’t have to be unique throughout the document, so rules based on class selectors usually apply to a selection of elements in a document. A class selector consists of a period ( . ) followed by the class name. class selectors can be applied to multiple elements of same or different types.

ex: here we define myclass class, and apply it to multiple elements as p and b.

.myclass {
color: white;
background-color: black;
}

<p class="myclass">A paragraph</p>
<b class="myclass">Another text</b>

ex: any p tag with "right" and "center" class gets its text aligned to right and center respectively. This style is same as hwat we used in id selector above.
p.right {text-align: right}
p.center {text-align: center}

ex:  .center {text-align: center} => any tag with center class gets its text aligned to center.

Grouping CSS selectors:

Just as we saw in the example for element selector where we applied the same attribute to multiple selectors, we can do the same for id and class selectors. The main motivation behind grouping multiple selectors is to save on size of CSS file, so that it's faster to load. These are 4 ways of grouping selectors:

1. grouping with comma as a separator: Here comma is used to separate the selectors. The attribute in parenthesis is applied to all the selectors. Selectors can be mixed, i.e id and class can be mixed.

ex: In this we group multiple selectors in same, i.e attribute color is applied to all class="red"(only for p elements since it's p.red), id="sub" and element="h1"

p.red, #sub, h1 { color: #f00; }

2. grouping using space as a separator (no comma): Here we don't use comma as CSS separators. This changes the meaning to imply a parent child relationship. The first selector is considerd as parent of subsequent selector (in nested form) and attribute is applied is applied to only those elements which is a descendant of all those selectors.

ex: .red #sub {color: #f00; } => Here the attribute color is applied to elements with id="sub" whose parent class="red" (i.e "sub" is a descendant of "red"). All the selectors here have to be single word selectors, as the parser will have no way of distinguishing selector with multiple words (they will be interpreted as different selectors by the parser)

<h1 class="red"> .... <h3 id="sub"> <p> my name </p> </h3> </h1> => Here color attribute will be applied to "p" element "my name" since the elemenet's parent has both class and id matching.

3. grouping by mixing separators with and without comma: This is mixing separators with and without comma (which is a combination of two styles #1 and #2 above and perfectly valid). 

ex: p.red, #sub, div a:link {color:red;} => Here p.red, #sub and "div a:link" are 3 diff selectors to which attribute "color" is applied. Note there is no comma b/w 3rd and 4th selector. The last selector is a compound selector and the rule is applied to The link pseudo class of the anchor elements that are descendants of a division (div tag).

4. grouping by having no space or comma separator: One other variation is to have no space between multiple class or id. In that case, it means apply the css property to element which matches all the given class and id. All examples above had attributes applied to any matching selector, but here, attribute is applied only if all the selectors match.

ex: #header.callout { } => here it says select all elements which have id=header and class=callout. NOTE: there's no space

ex: #header .callout { } => here there is  a space b/w #header and .callout. This becomes same as #2 above. So, this becomes css selector grouping with parent child relationship, i.e it selects all elements whose class="callout" and which are descendants of elements with id=header.

ex: .snip#header.code.red { } => We can mix as many id/header selectors that we like. Here there are 4 selectors, and we select all elements whose class=snip and id=header and class=code and class=red. This certainly is complex way of writing, but is valid anyway. We use these complex selectors to override individual selectors as .snip, .code, etc. We might want to apply certain property on class=snip or some other proerty on class=code, but we may want to apply some other property for elements which have both classes = snip and code. In such cases, we can use this style.

 

Properties and values:

As can be imagined, there are tons of properties and values, and it's not possible to remember or even know all of them. You should look online if you want to learn more about valid properties for various elements. This is a good ref for CSS properties:

https://www.w3schools.com/cssref/

We will just look at few common ones:

1. Colors and lengths:  The most common values in CSS are colors and lengths.

ex: color: #0ff; => This specs text color of an element to blue. We can specify value of color in 4 ways: name (eg red, blue), #rrggbb, #rgb and rgb(r,g,b), where r=0, g=0, b=0 gives coclor black, while r=255, g=255, b=255 gives color white.

ex: border-width: 5px => This specs width to be 5 pixels.  Length can be specified in many diff units as px (pixels), pt (pints where 1 point=1/72 of inch), cm (centimeter), in (inches), % (as percentage of size of element's parent)

2. display: The display property specifies the display behavior (the type of rendering box) of an element. By default, display mode is "block" which causes line breaks before and after each element. If we set display mode to "inline", that causes elements to be displayed side by side w/o line break. There are many more display modes.

https://www.w3schools.com/CSSref/pr_class_display.asp

ex: display: none; //this display mode doesn't display the element. This is used for drop down menu that you see in websites, where it shows other elements only on hovering mouse over it.

3. float and clear:

A floated element is one that’s outside of the normal flow of text, like a cutout. The text flows around these floated elements as long as there’s room. Floats could be used to lay out entire pages. Floats rely on two CSS properties: float and clear . The float property determines which side the element floats to, whereas the clear property determines how the element behaves with respect to other floated elements. Values for float are left , right , and none ; values for clear are left , right , both , and none .

ex: float: left;

Borders and backgrounds: Two of the most common things to style are borders and backgrounds.

1. Borders: A border has a width, a type, and a color. All three can be set separately using the properties border-width (a length, a width of 0px implies no visible border), border-style (a special property for borders), and border-color (a color):

ex:

.one { => this is the long notation
border-width: 5px;
border-style: solid;
border-color: #07f;
}

.one { => We can also use the short hand notation for the above border, with the triplet: width, style and color specified on a single line with spaces in between. We can also specify these triplet separately for each side of border, i.e border-top, border-bottom, etc.

border: 5px solid #07f;

}

<div class="one"></div>

There are many other properties of border that you can specify to custmize borders further. Look in ref link above.

2. Background: This allows images as background, which can be positioned, repeated, etc. Background is used very widely in joomla and other cms.

ex: this is the long notation where we specify all background properties with values. Here background property is applied on element "one"

one {
background-color: red;

background-image: url(background.png);

background-repeat: repeat;

background-position: top;

background-attachment: scroll;
}

ex: We can also set all background properties in one declaration. More details here: https://www.w3schools.com/cssref/css3_pr_background.asp

body {background: url(background.png) 50% 50% no-repeat fixed #f00; // this is the short notation, instead of using the long one above.

<body> <h1> Hello </h1> </body> //the above declared background property is applied to <body>  element

Page layout: CSS allows us to specify where to place elements on a given page, and how to display them. We'll learn about various CSS concepts below.

CSS Box model:

The CSS box model defines the dimensions of elements as they’re laid out on the page. Each html element can be considered a box. It consists of actual content of element, then a padding, border and margin around it. The size of each element is determined by it's width and height, then a padding around it, then a border and then a margin (margin is the space b/w this element and the next one).  The padding clears the area around the element before the border is drawn. padding is transparent. Then a border is drawn. Margin clears an area around the border. The element’s width and height is either defined explicitly or determined automatically by the browser based on the content and display mode. The total size of the element is the size after adding all of padding, border and margin to the element's size, as any other element has to be outside this box. Each of padding, border and margin have a width specified for top/bottom, left/right. Either all 4 values for the 4 sides can be given or just 1, 2 or 3 values can be given, and the browser will decode it based on some rules.

This is how it looks  with margin on the outermost and element in the innermost  => [ [ [ [  margin  [ [ [  border  [ [  padding  [   element   ]  padding   ] ]    border   ] ] ]   margin   ] ] ] ]

ex:  specifying all 3 for any content inside <p> element (in short notation). Since border=0px, border is not visible at all

.p {

border: 0px solid green; //border-top etc can also be specified in this format for each side
padding: 5px;
margin: 10px;

}

ex: border-width: 5px 10px 20px 30px; => This specs top=5px, right=10px, bot=20px and left=30px. Or if all 4 sides has same size, we could write "border-width: 5px;" We could also write this as 4 separate lines as below. Similarly for margin and padding, which we can specify as margin-top, padding-bottom, etc.
border-top-width: 5px;
border-right-width: 10px;
border-bottom-width: 20px;
border-left-width: 30px;

div tag:

The <div> tag defines a division or a section in an HTML document. The div element is a generic container with no particular semantic meaning. It's commonly used in web authoring for styling purposes, in conjunction with the style and class attributes. div is the one of the most commonly used elements you will find on website's CSS file. It's used in dividing a webpage in sections as header, main content, navigation, footer, etc, each with it's own distinct style. In HTML5 there is a <header> element, as well as a <nav>, <main>, <article>, <footer> and a couple other new elements that replace these div tags.

We can apply above properties to div element as:

div {
width: 2.5em;
height: 2.5em;
margin: 0.5em;
padding: 0.5em;
border: 5px dashed black;

display: block; //However, width and height properties don’t apply to inline elements, default width and height are chosen for that element
}

Now in html body, we can have something like:

<div> text 123 </div> <div> text 756 </div>

Now, we can make a whole page layout with header, article, navigation, footer, etc. Here's a link on creating layout using 5 different methods. Look at "CSS floats" for an example:

https://www.w3schools.com/html/html_layout.asp

 

-------

 

to define different styles for same type of html element.

 

this ..

this ..

styles can also be applied to html elements with particular attributes.
ex:
input[type=text] {background-color: blue}