Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • can/unix-command-line
  • gdurif/unix-command-line_dev
2 results
Show changes
Commits on Source (103)
Showing
with 3518 additions and 483 deletions
*.html
.DS_Store
.Rproj.user
/.quarto/
/_book/
*_cache/
pages:
stage: deploy
image: rocker/tidyverse
script:
- apt update && apt install -y libxt6
- quarto -v
- |
quarto render
mkdir public
cp -r _book/* public/
interruptible: true
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
---
title: SSH
author: "Laurent Modolo"
---
```{r include = FALSE}
if (!require("fontawesome")) {
install.packages("fontawesome")
}
library(fontawesome)
knitr::opts_chunk$set(echo = TRUE)
knitr::opts_chunk$set(comment = NA)
```
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" />
</a>
Objective: Learn basics of ssh connection in GNU/Linux
In the previous section, we have seen how to run scripts and complex commands on your computer. In this session we are going to learn to do that over the network.
Most of the content from this session are from [wikipedia.org](https://wikipedia.org)
## Network
First before talking about how to communicate over a network, we need to define what is a network in computational science. We can distinguish between two types of network, **circuit switching** networks and **packet switching** networks.
### circuit switching
Circuit switching is the historical telephonic network architecture. When device A wants to communicate with device B, it has to establish a connection over the network. In a circuit switching network, the connections between a chain of nodes (hopefully the shortest chain) are established and fixed. Device A connects to the closest node and ask connection to Device B, this node will do the same thing to the closest node to Device B, so on and so forth until the connection reach Device B.
If you try to call someone, who is already in a phone conversation, the line will be occupied.
![http://www.tcpipguide.com/free/diagrams/funcircuitswitching.png](./img/funcircuitswitching.png)
### packet switching
Packet switching is a method of grouping data over the network into packets. Each packet has a header and a payload. The header data can be read by each node to direct the packet to its destination. The header data also inform the Host 2 of the packets order. The payload contains the data that we want to transmit over the network. In packet switching, the network bandwidth is not pre-allocated like in circuit switching. Each packet is called a datagram.
> “A self-contained, independent entity of data carrying sufficient information to be routed from the source to the destination computer without reliance on earlier exchanges between this source and destination computer and the transporting network.”
![https://en.wikipedia.org/wiki/Packet_switching#/media/File:Packet_Switching.gif](./img/packet_switching.gif)
In a packet switching network when you send a flux of data (video, sound, etc.), you have the illusion of continuity like for process switching handled by the scheduler.
## **Internet Protocol** (IP)
> The **Internet Protocol** (**IP**) is the principal [communications protocol](https://en.wikipedia.org/wiki/Communications_protocol) in the [Internet protocol suite](https://en.wikipedia.org/wiki/Internet_protocol_suite) for relaying [datagrams](https://en.wikipedia.org/wiki/Datagram) across network boundaries. Its [routing](https://en.wikipedia.org/wiki/Routing) function enables [internetworking](https://en.wikipedia.org/wiki/Internetworking), and essentially establishes the [Internet](https://en.wikipedia.org/wiki/Internet).
IP has the task of delivering [packets](https://en.wikipedia.org/wiki/Packet_(information_technology)) from the source [host](https://en.wikipedia.org/wiki/Host_(network)) to the destination host solely based on the [IP addresses](https://en.wikipedia.org/wiki/IP_address) in the packet [headers](https://en.wikipedia.org/wiki/Header_(computing)). For this purpose, IP defines packet structures that [encapsulate](https://en.wikipedia.org/wiki/Encapsulation_(networking)) the data to be delivered. It also defines addressing methods.
The first major version of IP, [Internet Protocol Version 4](https://en.wikipedia.org/wiki/IPv4) (IPv4), is the dominant protocol of the Internet. Its successor is [Internet Protocol Version 6](https://en.wikipedia.org/wiki/IPv6) (IPv6), which has been in increasing [deployment](https://en.wikipedia.org/wiki/IPv6_deployment) on the public Internet since c. 2006.
### IPv4
An **IPv4** is composed of 4 digits ranging from 0 to 255 separated by `.` , which gives an address space of 4294967296 (2^32) addresses. Some combinations of **IPv4** are restricted:
| Address block | Address range | Number of addresses | Scope | Description |
| ------------------ | --------------------------- | ------------------- | --------------- | ------------------------------------------------------------ |
| 0.0.0.0/8 | 0.0.0.0–0.255.255.255 | 16777216 | Software | Current network[[6\]](https://en.wikipedia.org/wiki/IPv4#cite_note-rfc6890-6) (only valid as source address). |
| 10.0.0.0/8 | 10.0.0.0–10.255.255.255 | 16777216 | Private network | Used for local communications within a [private network](https://en.wikipedia.org/wiki/Private_network).[[7\]](https://en.wikipedia.org/wiki/IPv4#cite_note-rfc1918-7) |
| 100.64.0.0/10 | 100.64.0.0–100.127.255.255 | 4194304 | Private network | [Shared address space](https://en.wikipedia.org/wiki/IPv4_shared_address_space)[[8\]](https://en.wikipedia.org/wiki/IPv4#cite_note-rfc6598-8) for communications between a service provider and its subscribers when using a [carrier-grade NAT](https://en.wikipedia.org/wiki/Carrier-grade_NAT). |
| 127.0.0.0/8 | 127.0.0.0–127.255.255.255 | 16777216 | Host | Used for [loopback addresses](https://en.wikipedia.org/wiki/Loopback_address) to the local host.[[6\]](https://en.wikipedia.org/wiki/IPv4#cite_note-rfc6890-6) |
| 169.254.0.0/16 | 169.254.0.0–169.254.255.255 | 65536 | Subnet | Used for [link-local addresses](https://en.wikipedia.org/wiki/Link-local_address)[[9\]](https://en.wikipedia.org/wiki/IPv4#cite_note-rfc3927-9) between two hosts on a single link when no IP address is otherwise specified, such as would have normally been retrieved from a [DHCP](https://en.wikipedia.org/wiki/DHCP) server. |
| 172.16.0.0/12 | 172.16.0.0–172.31.255.255 | 1048576 | Private network | Used for local communications within a private network.[[7\]](https://en.wikipedia.org/wiki/IPv4#cite_note-rfc1918-7) |
| 192.0.0.0/24 | 192.0.0.0–192.0.0.255 | 256 | Private network | IETF Protocol Assignments.[[6\]](https://en.wikipedia.org/wiki/IPv4#cite_note-rfc6890-6) |
| 192.0.2.0/24 | 192.0.2.0–192.0.2.255 | 256 | Documentation | Assigned as TEST-NET-1, documentation and examples.[[10\]](https://en.wikipedia.org/wiki/IPv4#cite_note-rfc5737-10) |
| 192.88.99.0/24 | 192.88.99.0–192.88.99.255 | 256 | Internet | Reserved.[[11\]](https://en.wikipedia.org/wiki/IPv4#cite_note-rfc7526-11) Formerly used for [IPv6 to IPv4](https://en.wikipedia.org/wiki/6to4) relay[[12\]](https://en.wikipedia.org/wiki/IPv4#cite_note-rfc3068-12) (included [IPv6](https://en.wikipedia.org/wiki/IPv6) address block [2002::/16](https://en.wikipedia.org/wiki/IPv6_address#Special_addresses)). |
| 192.168.0.0/16 | 192.168.0.0–192.168.255.255 | 65536 | Private network | Used for local communications within a private network.[[7\]](https://en.wikipedia.org/wiki/IPv4#cite_note-rfc1918-7) |
| 198.18.0.0/15 | 198.18.0.0–198.19.255.255 | 131072 | Private network | Used for benchmark testing of inter-network communications between two separate subnets.[[13\]](https://en.wikipedia.org/wiki/IPv4#cite_note-rfc2544-13) |
| 198.51.100.0/24 | 198.51.100.0–198.51.100.255 | 256 | Documentation | Assigned as TEST-NET-2, documentation and examples.[[10\]](https://en.wikipedia.org/wiki/IPv4#cite_note-rfc5737-10) |
| 203.0.113.0/24 | 203.0.113.0–203.0.113.255 | 256 | Documentation | Assigned as TEST-NET-3, documentation and examples.[[10\]](https://en.wikipedia.org/wiki/IPv4#cite_note-rfc5737-10) |
| 224.0.0.0/4 | 224.0.0.0–239.255.255.255 | 268435456 | Internet | In use for [IP multicast](https://en.wikipedia.org/wiki/IP_multicast).[[14\]](https://en.wikipedia.org/wiki/IPv4#cite_note-rfc5771-14) (Former Class D network). |
| 240.0.0.0/4 | 240.0.0.0–255.255.255.254 | 268435455 | Internet | Reserved for future use.[[15\]](https://en.wikipedia.org/wiki/IPv4#cite_note-rfc3232-15) (Former Class E network). |
| 255.255.255.255/32 | 255.255.255.255 | 1 | Subnet | Reserved for the "limited [broadcast](https://en.wikipedia.org/wiki/Broadcast_address)" destination address.[[6\]](https://en.wikipedia.org/wiki/IPv4#cite_note-rfc6890-6)[[16\]](https://en.wikipedia.org/wiki/IPv4#cite_note-rfc919-16) |
### IPv6
An **IPv6** is composed of 8 groups of 4 digits long number separated by `:`.
The numbers are in hexadecimal format (number of base 16, randing from 0 to 9 and A to F).
Compared to **IPv4**, **IPv6** allows for 2^128 = 340,282,366,920,938,463,463,374,607,431,768,211,456 addresses (approximately 3.4×10^38).
For example, an IP address is: **2001:0db8:0000:0000:0000:ff00:0042:8329**
To display your VM IP addresses you can use the following command: `ip address show`
Local **IPv6** addresses start with **fe80::**
### **Domain Name System** (**DNS**)
Instead of using IP addresses in your everyday life, you often use the domain name. The DNS is composed of many DNS servers that are hierarchically organized and decentralized. By querying the DNS with a particular domain name, the correct name server will return the corresponding IP address. For most network tools, you can use domain names (URL) or IP addresses.
![dns resolver](./img/dns_resolver.svg)
### Transmission Control Protocol (**TCP**)
The **Transmission Control Protocol** (**TCP**) is one of the main [protocols](https://en.wikipedia.org/wiki/Communications_protocol) of the [Internet protocol suite](https://en.wikipedia.org/wiki/Internet_protocol_suite). TCP provide, reliable, ordered, and error-checked delivery of a stream of data between applications running on hosts communicating over an IP network.
- data arrives in-order
- data has minimal error (i.e., correctness)
- duplicate data is discarded
- lost or discarded packets are resent
- includes traffic congestion control
- Heavyweight (loots of checks)
### **User Datagram Protocol** (**UDP**)
UDP uses a simple [connectionless communication](https://en.wikipedia.org/wiki/Connectionless_communication) model with a minimum of protocol mechanisms.
- Unreliable
- Not ordered
- Broadcast (being connectionless, UDP can broadcast - sent packets can be addressed to be receivable by all devices on the subnet)
- Multicast (a single datagram packet can be automatically routed without duplication to a group of subscribers)
- Lightweight (no ordering of messages, no tracking connections, etc. It is a very simple transport layer designed on top of IP)
### Port
Higher, communication protocols like TCP and UDP, also define **port**. A **port** is a communication endpoint. When software wants to communicate overt TCP or UDP it will do so using a specific **port**. Each system has **port** numbers ranging from **0** to **65535**. **Port** numbered from **0** through **1023** are system **ports** used by well-known processes (you need specific rights to use them).
Here is a list of notable port numbers:
| Number | Assignment |
| ------ | ------------------------------------------------------------ |
| 20 | [File Transfer Protocol](https://en.wikipedia.org/wiki/File_Transfer_Protocol) (FTP) Data Transfer |
| 21 | [File Transfer Protocol](https://en.wikipedia.org/wiki/File_Transfer_Protocol) (FTP) Command Control |
| 22 | [Secure Shell](https://en.wikipedia.org/wiki/Secure_Shell) (SSH) Secure Login |
| 23 | [Telnet](https://en.wikipedia.org/wiki/Telnet) remote login service, unencrypted text messages |
| 25 | [Simple Mail Transfer Protocol](https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol) (SMTP) e-mail routing |
| 53 | [Domain Name System](https://en.wikipedia.org/wiki/Domain_Name_System) (DNS) service |
| 67, 68 | [Dynamic Host Configuration Protocol](https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol) (DHCP) |
| 80 | [Hypertext Transfer Protocol](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol) (HTTP) used in the [World Wide Web](https://en.wikipedia.org/wiki/World_Wide_Web) |
| 110 | [Post Office Protocol](https://en.wikipedia.org/wiki/Post_Office_Protocol) (POP3) |
| 119 | [Network News Transfer Protocol](https://en.wikipedia.org/wiki/Network_News_Transfer_Protocol) (NNTP) |
| 123 | [Network Time Protocol](https://en.wikipedia.org/wiki/Network_Time_Protocol) (NTP) |
| 143 | [Internet Message Access Protocol](https://en.wikipedia.org/wiki/Internet_Message_Access_Protocol) (IMAP) Management of digital mail |
| 161 | [Simple Network Management Protocol](https://en.wikipedia.org/wiki/Simple_Network_Management_Protocol) (SNMP) |
| 194 | [Internet Relay Chat](https://en.wikipedia.org/wiki/Internet_Relay_Chat) (IRC) |
| 443 | [HTTP Secure](https://en.wikipedia.org/wiki/HTTP_Secure) (HTTPS) HTTP over TLS/SSL |
Nowadays, **ports** provide multiplexing, which means that multiple service or communication session can use the same **port** number.
## SSH
There are numerous other protocols ([RTP](https://en.wikipedia.org/wiki/Real-time_Transport_Protocol) for example). But most of them run over the **TCP** and **UDP** protocols. **SSH** or **Secure Shell** is one of them. **SSH** is a [cryptographic](https://en.wikipedia.org/wiki/Cryptography) [network protocol](https://en.wikipedia.org/wiki/Network_protocol) for operating network services securely over an unsecured network.
**SSH** use a client-server architecture, you use an **SSH client** to connect to an **SSH server**. By default most Linux distribution don’t come with an **SSH server** installed. For the IFB, **SSH** connection is the default way to connect to your VMs, so you should have an **SSH** sever running.
Find the name of the **SSH** server process
<details><summary>Solution</summary>
<p>
```sh
ps -el | grep "ssh"
```
</p>
</details>
SSH uses [Public-key cryptography (or asymmetric cryptography](https://en.wikipedia.org/wiki/Public-key_cryptography)), to secure its communications.
### Public-key cryptography
[Public-key cryptography (or asymmetric cryptography](https://en.wikipedia.org/wiki/Public-key_cryptography)), is a cryptographic system which uses pairs of [keys](https://en.wikipedia.org/wiki/Cryptographic_key): *public keys* (which may be known to others), and *private keys* (which may never be known by any except the owner).
A cryptographic algorithm is used to generate a pair of *public* and *private* keys from a large random number. Then, the 3 following scheme can be used to secure communication:
### Communicate with the server
The server sent a public key to the client on the first connection.
![public_key_encryption](./img/public_key_encryption.png)
### Share a secret
Can be used to share public keys (see [Diffie-Hellman)](https://fr.wikipedia.org/wiki/%C3%89change_de_cl%C3%A9s_Diffie-Hellman).
![public_key_shared_secret](./img/public_key_shared_secret.png)
### Authentification
- The server sends a random string of characters to the client
- The client crypt the random string and send it back to the server
- The server decrypt the message with the client public key and compare it to the random string
![private_key_signing](./img/private_key_signing.png)
## SSH Server
By default, on the IFB, password authentication is disabled to enforce the use of public key based authentication. To learn `ssh` command we are going to enable this option on your VMs. Find the`sshd` configuration file and open it with the editor of your choice.
<details><summary>Solution</summary>
<p>
```sh
vim /etc/ssh/sshd_config
```
</p>
</details>
This file is own by **root**, you need to get **root** access to your account.
<details><summary>Solution</summary>
<p>
```sh
docker run -it --volume /:/root/chroot alpine sh -c "chroot /root/chroot /bin/bash -c 'usermod -a -G sudo etudiant'" && su etudiant
```
</p>
</details>
Using the `sudo` command edit the configuration file to set **PasswordAuthentication** to **yes** and add the following lines:
```
AllowUsers etudiant student
PermitRootLogin no
```
The `sshd` (SSH Daemon) process in launched and managed by `systemd`. You can manage `systemd` service with the `systemctl` command. Try this command without any arguments. You can search for `sshd` by typing `/sshd` and pressing `enter`. You can leave the `systemctl` view by pressing `q`.
To apply our modification to the `sshd` server configuration, we need to restart the corresponding *service*. You can use the following command:
```sh
sudo systemctl restart sshd
```
You can use the keyword `start`, `stop` and `status` to manage `systemd` services.
Check the **status** of your `sshd` *service*.
<details><summary>Solution</summary>
<p>
```sh
sudo systemctl status sshd
```
</p>
</details>
You are going to create an account for another member of the formation to connect on your VM.
```sh
sudo useradd -m -s /bin/bash -g users student
sudo passwd student
```
Give the password and your IP to another member of your choice (`ip address show`).
## SSH client
To connect of an SSH server you can use the following command:
```sh
ssh login@IP_adress
```
Use this command to connect to another student VM.
On the first connection, `ssh` ask you to accept the public key of the server (key fingerprint). With that in the future if someone tries to fool you by impersonating the ssh server, he won’t be able to do it without the corresponding private key.
You can close the connection by pressing `ctrl` + `d` or with the command `exit`.
Check the content of the `~/.ssh/` folder, where is saved the server public key ?
Congratualtion you are connected on a VM through another VM !
### Key authentication
Every time, that you want to connect to the ssh server, you have to type your account password, this password is encrypted and send over the network. Instead you can use a pair of private and public key to authenticate yourself.
First you have to generate a pair of key with the command:
```sh
ssh-keygen -t ed25519 -C "your.mail@ens-lyon.fr"
```
The option `-t` specifies the algorithm to use while `-C` specify comment associated with the key (generally the email of the person generating the key). You can check the **man**ual and internet to compare the different available algorithms.
It is a good practice to name a given pair of keys after the name of the server, on which you want to use those keys.
You can use the name `/home/etudiant/.ssh/id_ed25519_otherVM`
Then as an additional security measure, you can restrict the usage of your private key by defining a password. You will need the password and the key file to authenticate yourself.
The generated keys are in the folder `~/.ssh/`
Then you need to make a copy of your public key (`.pub`) on the sshd server.
```sh
ssh-copy-id -i ~/.ssh/id_ed25519_otherVM.pub login@IP_adresse
```
Note that for security reason, only you should be able to read and write within your `.ssh` folder (you don’t want someone else to mitigate with your keys). You can use the command `chmod 600 .ssh/*`
You can try to log on the server using the key with the following command:
```sh
ssh login@IP_adress -i ~/.ssh/id_ed25519_otherVM
```
`ssh` Should ask for your key password instead of the student account password.
Congratulations, you authenticated yourself on a remote server without sending your password over the network !
## SSH based tools
Sometime, you want to do other things than executing commands on a remove computer. For example, you may want to transfer files over the network.
### scp
The `scp` command comes with the `ssh` client installation you can use it to transfer files from your computer to the ssh sever:
```sh
scp local/path login@IP_adress:remote/path
```
> You can use a relative remote path, where the ":" correspond to your home folder on the remote server.
You can also retrieve files from the server:
```sh
scp login@IP_adress:remote/path local/path
```
To transfer directory you can use the `-r` witch
### rsync
`scp` is a basic command for file transfer. If you want advanced process bar and file integrity checking, you can use the `rsync` command instead.
For example
```sh
rsync -auv local/path login@IP_adress:remote/path
```
Will only transfer files from `local/path` not already present in `remote/path`. The `-c` switch will compute a checksum of the file locally and remotely to be certain that they are identical.
### sshfs
You can use the `sshfs` command to mount a remote folder over ssh on your computer.
## SSH tips
### IFB authentication
The default authentication method for the IFB uses keys generated with the `rsa` algorithm
```sh
ssh-keygen -t rsa -b 4096 -C "your.mail@ens-lyon.fr"
```
The `-b` option set the size of the key.
Instead of using the `ssh-copy-id` command, you are going to copy paste your public key into your [IFB configuration page.](https://biosphere.france-bioinformatique.fr/cloudweb_account/settings/edit)
You can now use the [RainBio catalogue](https://biosphere.france-bioinformatique.fr/catalogue/) to launch any available VMs and connect to is with SSH from your current VM.
### SSH configuration
Long ssh command can be tedious to use. This is why we are now going to explore the last file in the `.ssh` folder: `.ssh/config`.
This file is decomposed in different `Host` sections like the following to connect yourself to [the ssh server of the ens](https://instella.ens-lyon.fr/stella/intra/ent-ssh.html).
```yaml
Host ens
HostName ssh.ens-lyon.fr
User <login>
IdentitiesOnly yes
IdentityFile ~/.ssh/id_ens
PreferredAuthentications publickey,password,
```
- `HostName` define the server url or IP address
- `User` the login to use
- `Identit*` define the key authentication mechanism
- `PreferredAuthentications` tells the order of the authentication mechanism to try
With this configuration you can use the command:
```sh
ssh ens
```
To connect to the `ssh.ens-lyon.fr` server.
You can also apply ssh configuration to all the `Host` with the following:
```yaml
Host *
Compression yes
ServerAliveInterval 36000
ControlMaster auto
ControlPersist yes
ControlPath ~/.ssh/socket-%r@%h:%p
```
Here we say that we want to enable compression for all the connections. And that we want each connection to stay alive 3600 seconds. The connection is maintained with socked files in the `~/.ssh/` folder with names starting with `socket-`. This also means that if you connect more than once to the same server, the same connection will be used.
Sometime you want to connect to a ssh server from an intermediate (or many intermediate) ssh server. To do that you can use the **ProxyJump** option. For example, you can connect to a computer running a ssh server within the ens with the following config.
```yaml
Host work-ens
ProxyJump ens
HostName ip.ip.ip.ip
User login
IdentitiesOnly yes
IdentityFile ~/.ssh/id_work
PreferredAuthentications publickey,password,
```
With the command `ssh work-ens`, the `ssh` client is going to first connect to `ens` and then from `ens` to the `ip.ip.ip.ip` server.
> We have used the following commands:
>
> - ssh to establish ssh connection
> - sytemctl to manage system daemons
> - scp to copy files
> - rsync to copy files
In the next session, we are going to learn how to [install systemwide programs](./11_install_system_programs.html) like the one managed by `systemd`
---
title: Install system programs
author: "Laurent Modolo"
---
```{r include = FALSE}
if (!require("fontawesome")) {
install.packages("fontawesome")
}
library(fontawesome)
knitr::opts_chunk$set(echo = TRUE)
knitr::opts_chunk$set(comment = NA)
```
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" />
</a>
Objective: Learn how to install programs in GNU/Linux
As we have seen in the [4 Unix file system](http://perso.ens-lyon.fr/laurent.modolo/unix/4_unix_file_system.html#lib-and-usrlib) session, programs are files that contain instruction for the computer to do things. Those files can be in binary or text format (with a [shebang](http://perso.ens-lyon.fr/laurent.modolo/unix/9_batch_processing.html#shebang)). Any of those files, present in a folder of the [**PATH**](http://perso.ens-lyon.fr/laurent.modolo/unix/9_batch_processing.html#path) variable are executable anywhere by the user. For system wide installation, the program files are copied within shared folder path containained in the [**PATH**](http://perso.ens-lyon.fr/laurent.modolo/unix/9_batch_processing.html#path) variable.
Developers don’t want to reinvent the wheel each time they want to write complex instruction in their programs, this is why they use shared library of pre-written complex instruction. This allows for quicker development, fewer bugs (we only have to debug the library once and use it many times), and also [better memory management](http://perso.ens-lyon.fr/laurent.modolo/unix/6_unix_processes.html#processes-tree) (we only load the library once and it can be used by different programs).
## Package Manager
However, interdependencies between programs and libraries can be a nightmare to handle manually this is why most of the time when you install a program you will use a [package manager](https://en.wikipedia.org/wiki/Package_manager). [Package managers](https://en.wikipedia.org/wiki/Package_manager) are system tools that will handle automatically all the dependencies of a program. They rely on **repositories** of programs and library which contains all the information about the trees of dependence and the corresponding files (**packages**).
Systemwide installation steps:
- The user asks the package manager to install a program
- The **package manager** queries its repository lists to search for the most recent **package** version of the program (or a specific version)
- The **package manager** construct the dependency tree of the program
- The **package manager** check that the new dependency tree is compatible with every other installed program
- The **package manager** install the program **package** and all its dependencies **packages** in their correct version
The main difference between GNU/Linux distribution is the package manager they use
- Debian / Ubuntu: [apt](https://en.wikipedia.org/wiki/APT_(Debian))
- CentOS / RedHat: [yum](https://en.wikipedia.org/wiki/YUM_(software))
- ArchLinux: [pacman](https://en.wikipedia.org/wiki/Pacman_(Arch_Linux))
- SUSE / OpenSUSE: [zypper](https://en.wikipedia.org/wiki/Zypper)
- Gentoo: [portage](https://en.wikipedia.org/wiki/Portage_(software))
- Alpine: [apk](https://wiki.alpinelinux.org/wiki/Alpine_newbie_apk_packages)
Packages manager install the packages in **root** owned folders, you need **root** access to be able to use them.
<details><summary>Solution</summary>
<p>
```sh
docker run -it --volume /:/root/chroot alpine sh -c "chroot /root/chroot /bin/bash -c 'usermod -a -G sudo etudiant'" && su etudiant
```
</p>
</details>
### Installing R
**R** is a complex program that relies on loots of dependencies. Your current VM run on Ubuntu, so we are going to use the `apt` tool (`apt-get` is the older version of the `apt` command, `synaptic` is a graphical interface for `apt-get`).
You can check the **r-base** package dependencies on the website [packages.ubuntu.com](https://packages.ubuntu.com/focal/r-base). Not too much dependency ? Check the sub-package **r-base-core**.
You can check the **man**ual of the `apt` command to install **r-base-core**.
<details><summary>Solution</summary>
<p>
```sh
sudo apt install r-base-core
```
</p>
</details>
What is the **R** version that you installed ? Is there a newer version of **R** ?
### Adding a new repository
You can check the list of repositories that `apt` checks in the file `/etc/apt/sources.list`.
You can add the official cran repository to your repositories list:
```sh
sudo add-apt-repository 'deb https://cloud.r-project.org/bin/linux/ubuntu <release_name>-cran40/'
```
You can use the command `lsb_release -sc` to get your **release name**.
Then you must add the public key of this repository:
```sh
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9
```
### Updating the repository list
You can now use `apt` to update your repository list dans try to reinstall **r-base-core**
<details><summary>Solution</summary>
<p>
```sh
sudo apt update
```
</p>
</details>
The command gives you a way to list all the upgradable **packages**, which version of **R** can you install now ?
You can upgrade all the upgradable **packages**.
<details><summary>Solution</summary>
<p>
```sh
sudo apt upgrade
```
</p>
</details>
With the combination of `update` and `upgrade` you can keep your whole system up to date the even the kernel files is just another package. You can use `apt` to search for the various versions of the `linux-image`.
<details><summary>Solution</summary>
<p>
```sh
sudo apt search linux-image
```
</p>
</details>
### Language specific package manager
If it’s not a good idea to have different **package manager** on the same system (they don’t know how the dependencies are handled by the other’s manager). You will also encounter language specific package manager:
- `ppm` for Perl
- `pip` for Python
- `npm` for JavaScript
- `cargo` for Rust
- `install.packages` for R
- ...
These **package managers** allow you to make installation local to the user, which is advisable to avoid any conflict with the **packages manager** of the system.
For example, you can use the following command to install `glances` system wide with `pip`
```sh
sudo pip3 install glances
```
You can now try to install `glances` with `apt`
What is the `glances` version installed with `apt`, what is the one installed with `pip` ? What is the version of the `glances` of your **PATH** ?
Next-time use `pip` with the `--user` switch.
## Manual installation
Sometimes, a specific tool that you want to use will not be available through a **package manager**. If you are lucky, you will find a **package** for your distribution. For `apt` the **package** are `.deb` files.
For example, you can download `simplenote` version 2.7.0 for your architecture [here](https://github.com/Automattic/simplenote-electron/releases/tag/v2.7.0).
<details><summary>Solution</summary>
<p>
```sh
wget https://github.com/Automattic/simplenote-electron/releases/download/v2.7.0/Simplenote-linux-2.7.0-amd64.deb
```
</p>
</details>
You can then use `apt` to install this file.
## From sources
If the program is open source, you can also [download the sources](https://github.com/Automattic/simplenote-electron/archive/v2.7.0.tar.gz) and build them.
<details><summary>Solution</summary>
<p>
```sh
wget https://github.com/Automattic/simplenote-electron/archive/v2.7.0.tar.gz
```
</p>
</details>
You can use the command `tar -xvf` to extract this archive
When you go into the `simplenote-electron-2.7.0` folder, you can see a `Makefile` this means that you can use the `make` command to build Simplenote from those files. `make` is a tool that read recipes (`Makefiles`) to build programs.
You can try to install `node` and `npx` with `apt`. What happened ?
<details><summary>Solution</summary>
<p>
```sh
sudo apt install nodejs
```
</p>
</details>
You can use the [https://packages.ubuntu.com/](https://packages.ubuntu.com/) to search the name of the package containing the `libnss3.so` file.
<details><summary>Solution</summary>
<p>
```sh
sudo apt install libnss3
```
</p>
</details>
What now ? Installing dependencies manually is an iterative process...
<details><summary>Solution</summary>
<p>
```sh
sudo apt install libnss3 libatk1.0-dev libatk-bridge2.0-0 libgdk-pixbuf2.0-0 libgtk-3-0 libgbm1
```
</p>
</details>
Yay we should have every lib !
What now ? A nodejs dependency is missing... After, some query on the internet we can find the solution...
<details><summary>Solution</summary>
<p>
```sh
sudo apt install libnss3 libatk1.0-dev libatk-bridge2.0-0 libgdk-pixbuf2.0-0 libgtk-3-0 libgbm1
npm install --save-dev electron-window-state
```
</p>
</details>
And now you understand why program packaging takes time in a project, and why it’s important !
You can finalize the installation with the command `make install`. Usually the command to build a tool is available in the `README.md` file of the project.
Read the `README` file of the [fastp](https://github.com/OpenGene/fastp) program to see which methods of installation are available.
> We have used the following commands:
>
> - apt to install packages on Ubuntu
> - pip3 to install Python packages
> - npm to install Nodejs packages
> - make to build programs from sources
Installing programs and maintain different versions of a program on the same system is a difficult task. In the next session, we will learn how to use [virtualization](./12_virtualization.html) to facilitate our job.
---
title: Virtualization
author: "Laurent Modolo"
---
```{r include = FALSE}
if (!require("fontawesome")) {
install.packages("fontawesome")
}
library(fontawesome)
knitr::opts_chunk$set(echo = TRUE)
knitr::opts_chunk$set(comment = NA)
```
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" />
</a>
Objective: Learn how to build virtual images or container of a system
If a computer can run any programs, it can also run a program simulating another computer. This is a core concept of virtualization. The software that creates the **guest** system (the simulated computer) is called a **hypervisor** or **virtual machine monitor**.
You can save the state of the whole **guest** system using a **snapshot**. The **snapshots** can then be executed on any other **hypervisor**. This as several benefits:
- If the **host** has a hardware failure, the **snapshots** can be executed on another **host** to avoid service interruption
- For scalable system, as many **guest** systems as necessary can be launched adaptively on many **host** systems to handle peak consumption. When the peak is over, we can easily stop the additional **guest** systems.
- For computing science a **snapshot** of a suite of tools allows to you run the same computation as it also captures all the software (and simulated) hardware environment.
To avoid the overhead of simulating every component of the **guest** system, which means that the **hypervisor** programs must run code that simulates a given hardware and code that simulate the **guest** programs running on this hardware, some part of the **host** system can be shared (with control) with the **guest** system.
There are different levels of virtualisation which correspond to different levels of isolation between the virtual machine (**guest**) and the real computer (**host**).
## Full virtualization
A key challenge for full virtualization is the interception and simulation of privileged operations, such as I/O instructions. The effects of every operation performed within a given virtual machine must be kept within that virtual machine – virtual operation cannot be allowed to alter the state of any other virtual machine, the control program, or the hardware. Some machine instructions can be executed directly by the hardware, since their effects are entirely contained within the elements managed by the control program, such as memory locations and arithmetic registers. But other instructions that would "pierce the virtual machine" cannot be allowed to execute directly; they must instead be trapped and simulated. Such instructions either access or affect state information that is outside the virtual machine.
## Paravirtualization
In paravitualization, the virtual hardware of the **guest** system is similar to the hardware of the **host**. The goal is to reduce the portion of the **guest** execution time spent to simulate hardware which is the same as the **host** hardware. The paravirtualization provides specially defined **hooks** to allow the **guest** and **host** to request and acknowledge these tasks, which would otherwise be executed in the virtual domain (where execution performance is worse).
A hypervisor provides the virtualization of the underlying computer system. In [full virtualization](https://en.wikipedia.org/wiki/Full_virtualization), a guest operating system runs unmodified on a hypervisor. However, improved performance and efficiency is achieved by having the guest operating system communicate with the hypervisor. By allowing the guest operating system to indicate its intent to the hypervisor, each can cooperate to obtain better performance when running in a virtual machine. This type of communication is referred to as paravirtualization.
## OS-level virtualization
**OS-level virtualization** is an [operating system](https://en.wikipedia.org/wiki/Operating_system) paradigm in which the [kernel](https://en.wikipedia.org/wiki/Kernel_(computer_science)) allows the existence of multiple isolated [user space](https://en.wikipedia.org/wiki/User_space) instances. Such instances, called **containers** may look like real computers from the point of view of programs running in them. Programs running inside a container can only see the container's contents and devices assigned to the container.
## VirtualBox
VirtualBox is own by oracle, you can add the following repository to get the last version:
<details><summary>Solution</summary>
<p>
```sh
docker run -it --volume /:/root/chroot alpine sh -c "chroot /root/chroot /bin/bash -c 'usermod -a -G sudo etudiant'" && su etudiant
```
</p>
</details>
```sh
wget -q -O- http://download.virtualbox.org/virtualbox/debian/oracle_vbox_2016.asc | sudo apt-key add -
sudo apt update
sudo apt install virtualbox
sudo usermod -G vboxusers -a $USER
```
The first thing that we need to do with virtual box is to create a new virtual machine. We want to install Ubuntu 20.04 on it.
```sh
VBoxManage createvm --name Ubuntu20.04 --register
```
We create a virtual hard disk for this VM:
```sh
VBoxManage createhd --filename Ubuntu20.04 --size 14242
```
We can then configure the VM, we use the Ubuntu presets.
```sh
VBoxManage modifyvm Ubuntu20.04 --ostype Ubuntu
```
We set the virtual RAM
```sh
VBoxManage modifyvm Ubuntu20.04 --memory 1024
```
We add a virtual IDE peripheric storage on which we can boot on.
```sh
VBoxManage storagectl Ubuntu20.04 --name IDE --add ide --controller PIIX4 --bootable on
```
And add an ubuntu image to this IDE device
```sh
wget https://releases.ubuntu.com/20.10/ubuntu-20.10-live-server-amd64.iso
VBoxManage storageattach Ubuntu20.04 --storagectl IDE --port 0 --device 0 --type dvddrive --medium "/home/etudiant/ubuntu-20.10-live-server-amd64.iso"
```
Add a network interface
```sh
VBoxManage modifyvm Ubuntu20.04 --nic1 nat --nictype1 82540EM --cableconnected1 on
```
And then start the VM to launch the `ubuntu-20.10-live-server-amd64.iso` installation
```sh
VBoxManage startvm Ubuntu20.04
```
Why did this last command fail ? Which kind of virtualisation VirtualBox is using ?
## Docker
Docker is an **OS-level virtualization** system where the virtualization is managed by the `docker` daemon.
You can use the `systemctl` command and the `/` key to search for this daemon.
Like VirtualBox, you can install system programs within a container.
Prebuilt containers can be found on different sources like [the docker hub](https://hub.docker.com/) or [the biocontainers registry](https://biocontainers.pro/registry).
Launching a container
```sh
docker run -it alpine:latest
```
You can check your user name
<details><summary>Solution</summary>
<p>
```sh
echo $USER
id
```
</p>
</details>
Launching a background container
```sh
docker run -d -p 8787:8787 -e PASSWORD=yourpasswordhere rocker/rstudio:3.2.0
```
You can check the running container with :
```sh
docker ps
```
Run a command within a running container:
```sh
docker exec <CONTAINER ID> id
```
Stopping a container:
```sh
docker stop <CONTAINER ID>
```
Deleting a container:
```sh
docker rm <CONTAINER ID>
```
Deleting a container image
```sh
docker rmi rocker/rstudio:3.2.0
```
Try to run the `mcr.microsoft.com/windows/servercore:ltsc2019` container, what is happening ?
### Building your own container
You can also create your own container by writing a container recipe. For Docker this file is named `Dockerfile`
The first line of such recipe is a `FROM` statement. You don't start from scratch like in VirtualBox, but from a bare distribution:
```dockerfile
FROM ubuntu:20.04
```
From this point you can add instructions
`COPY` will copy files from the `Dockerfile` directory to a path inside the container
```dockerfile
COPY .bashrc /
```
`RUN`will execute command inside the container
```dockerfile
RUN apt updatge && apt install -y htop
```
You can then build your container:
```sh
docker build ./ -t 'ubuntu_with_htop'
```
## Singularity
Like Docker, Singularity is an **OS-level virtualization**. This main difference with docker is that the user is the same within and outside a container. Singularity is available on the [neuro.debian.net](http://neuro.debian.net/install_pkg.html?p=singularity-container) repository, you can add this source with the following commands:
```sh
wget -O- http://neuro.debian.net/lists/focal.de-md.full | sudo tee /etc/apt/sources.list.d/neurodebian.sources.list
sudo apt-key adv --recv-keys --keyserver hkp://pool.sks-keyservers.net:80 A5D32F012649A5A9
sudo apt-get update
sudo apt-get install singularity-container
```
Launching a container
```sh
singularity run docker://alpine:latest
```
You can check your user name
<details><summary>Solution</summary>
<p>
```sh
echo $USER
id
```
</p>
</details>
Executing a command within a container
```sh
singularity exec docker://alpine:latest apk
```
---
title: First step in a terminal
title: Understanding a computer
author: "Laurent Modolo"
---
# Understanding a computer
```{r include = FALSE}
if (!require("fontawesome")) {
install.packages("fontawesome")
}
library(fontawesome)
knitr::opts_chunk$set(echo = TRUE)
knitr::opts_chunk$set(comment = NA)
```
[![cc_by_sa](./img/cc_by_sa.png)](http://creativecommons.org/licenses/by-sa/4.0/)
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" />
</a>
Objective: understand the relations between the different components of a computer
---
## Which parts are necessary to define a computer ?
# Which parts are necessary to define a computer ?
## Computer components
### CPU (Central Processing Unit)
---
![CPU](./img/amd-ryzen-7-1700-cpu-inhand1-2-1500x1000.jpg){width=100%}
# Computer components
### Memory
## CPU (Central Processing Unit)
![CPU](./img/amd-ryzen-7-1700-cpu-inhand1-2-1500x1000.jpg)
#### RAM (Random Access Memory)
## Memory
![RAM](./img/ram.png){width=100%}
### RAM (Random Access Memory)
<img src="./img/220px-Swissbit_2GB_PC2-5300U-555.jpg" alt="RAM" style="zoom:150%;" />
#### HDD (Hard Disk Drive) / SSD (Solid-State Drive)
### HDD (Hard Disk Drive) / SSD (Solid-State Drive)
<img src="./img/220px-Laptop-hard-drive-exposed.jpg" alt="HDD" style="zoom:150%;" />
<img src="./img/220px-SSD_Samsung_960_PRO_512GB_-_front_and_back_-_2018-05-27.jpg" alt="SSD" style="zoom:150%;" />
![HDD](./img/SSD.jpeg){width=100%}
![SSD](./img/hdd.png){width=100%}
## Motherboard
![motherboard](./img/motherboard.jpg)
### Motherboard
## GPU (Graphical Processing Unit)
![GPU](./img/foundation-100046736-orig.jpg)
![motherboard](./img/motherboard.jpg){width=100%}
## Alimentation
![Alim](./img/LD0003357907_2.jpg)
### GPU (Graphical Processing Unit)
---
![GPU](./img/foundation-100046736-orig.jpg){width=100%}
# Computer model: universal Turing machine
### Alimentation
![Alim](./img/LD0003357907_2.jpg){width=100%}
---
## Computer model: universal Turing machine
![width:20% height:20%](./img/lego_turing_machine.jpg)
![width:20% height:20%](./img/lego_turing_machine.jpg){width=100%}
---
# As simple as a Turing machine ?
## As simple as a Turing machine ?
![universal_truing_machine](./img/universal_truing_machine.png)
![Universal Truing Machine](./img/universal_truing_machine.png){width=100%}
- A tape divided into cells, one next to the other. Each cell contains a symbol from some finite alphabet.
- A head that can read and write symbols on the tape and move the tape left and right one (and only one) cell at a time.
......@@ -59,7 +68,7 @@ Objective: understand the relations between the different components of a comput
---
# Basic Input Output System (BIOS)
## Basic Input Output System (BIOS)
> Used to perform hardware initialization during the booting process (power-on startup), and to provide runtime services for operating systems and programs.
......@@ -69,7 +78,7 @@ Objective: understand the relations between the different components of a comput
---
# Unified Extensible Firmware Interface (UEFI)
## Unified Extensible Firmware Interface (UEFI)
Advantages:
......@@ -86,50 +95,54 @@ Disadvantages:
---
# Operating System (OS)
## Operating System (OS)
> A system software that manages computer hardware, software resources, and provides common services for computer programs.
- The first thing loaded by the BIOS/UEFI
- The first thing on the tape of a Turing machine
## Kernel
### Kernel
> The kernel provides the most basic level of control over all of the computer's hardware devices. It manages memory access for programs in the RAM, it determines which programs get access to which hardware resources, it sets up or resets the CPU's operating states for optimal operation at all times, and it organizes the data for long-term non-volatile storage with file systems on such media as disks, tapes, flash memory, etc.
![Kernel](./img/220px-Kernel_Layout.svg.png)
![Kernel](./img/220px-Kernel_Layout.svg.png){width=100%}
---
# UNIX
## UNIX
> Unix is a family of multitasking, multiuser computer operating systems that derive from the original AT&T Unix,
[![Unix history](./img/1920px-Unix_timeline.en.svg.png)](https://upload.wikimedia.org/wikipedia/commons/7/77/Unix_history-simple.svg)
[![Unix history](./img/1920px-Unix_timeline.en.svg.png){width=100%}](https://upload.wikimedia.org/wikipedia/commons/b/b5/Linux_Distribution_Timeline_21_10_2021.svg)
The ones you are likely to encounter:
- [macOS](https://en.wikipedia.org/wiki/MacOS)
- [BSD (Berkeley Software Distribution) variant](https://www.freebsd.org/)
- [GNU/Linux](https://www.kernel.org/)
The philosophy of UNIX is to have a large number of small software which do few things but to them well.
# GNU/Linux
## GNU/Linux
Linux is the name of the kernel which software, to get a full OS, Linux is part of the [GNU Project](https://www.gnu.org/).
The GNU with Richard Stallman introduced the notion of Free Software:
1. The freedom to run the program as you wish, for any purpose.
2. The freedom to study how the program works, and change it so it does your computing as you wish. Access to the source code is a precondition for this.
3. The freedom to redistribute copies so you can help others.
4. The freedom to distribute copies of your modified versions to others. By doing this you can give the whole community a chance to benefit from your changes. Access to the source code is a precondition for this.
![Richard Stallman](https://audio-video.gnu.org/video/TEDxGE2014_Stallman05_LQ.webm)
You can find a [list of software licenses](https://www.gnu.org/licenses/license-list.html)
<video width="100%" controls>
<source src="https://audio-video.gnu.org/video/TEDxGE2014_Stallman05_LQ.webm" type="video/webm">
Your browser does not support the video tag.
</video>
[Instead of installing GNU/Linux on your computer you are going to learn to use the IFB Cloud](http://perso.ens-lyon.fr/laurent.modolo/unix/2_using_the_ifb_cloud.html)
See this [presentation](https://plmlab.math.cnrs.fr/gdurif/presentation_foss/-/blob/main/presentation/presentation_DURIF_foss.pdf) (in french) for a quick introduction about **software license** and **free/open source software**.
[Instead of installing GNU/Linux on your computer, you are going to learn to use the IFB Cloud.](./2_using_the_ifb_cloud.html)
---
title: IFB (Institu Français de bioinformatique) Cloud
title: IFB (Institut Français de bio-informatique) Cloud
author: "Laurent Modolo"
---
# IFB (Institu Français de bioinformatique) Cloud
```{r include = FALSE}
if (!require("fontawesome")) {
install.packages("fontawesome")
}
library(fontawesome)
knitr::opts_chunk$set(echo = TRUE)
knitr::opts_chunk$set(comment = NA)
```
[![cc_by_sa](./img/cc_by_sa.png)](http://creativecommons.org/licenses/by-sa/4.0/)
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" />
</a>
Objective: Start and connect to an appliance on the IFB cloud
Instead of working on your computer where you don't have an Unix-like OS or have limited right, we are going to use the [IFB (Institu Français de bioinformatique) Cloud]( https://biosphere.france-bioinformatique.fr/).
Instead of working on your computer where you don't have an Unix-like OS or have limited right, we are going to use the [IFB (Institut Français de bio-informatique) Cloud]( https://biosphere.france-bioinformatique.fr/).
## Creating an IFB account
1. Access the [**https://biosphere.france-bioinformatique.fr/**](**https://biosphere.france-bioinformatique.fr/**) website
2. On the top righ(First) step with GNU/Linux
Instead of working on your computer where you don't have an Unix-like OS or have limited right, we are going to use the [IFB (Institu Français de bioinformatique) Cloud]( https://biosphere.france-bioinformatique.fr/). For this you will need:
1. Access the [**https://biosphere.france-bioinformatique.fr/**](**https://biosphere.france-bioinformatique.fr/**) website
2. On the top right of the screen click on <img src="/Users/laurent/Documents/formations/2020_08_UNIX/img/signin_ifb.png" alt="sign in" style="zoom:150%;" />
3. Then click on ![login](/Users/laurent/Documents/formations/2020_08_UNIX/img/login_ifb.png)
1. Access the [**https://biosphere.france-bioinformatique.fr/**](https://biosphere.france-bioinformatique.fr/) website
2. On the top right of the screen click on <img src="./img/signin_ifb.png" alt="sign in" style="zoom:150%;" />
3. Then click on ![login](./img/login_ifb.png)
4. Use the **Incremental search field** to select your identity provider (CNRS / ENS de Lyon / etc.)
5. Login
6. Complete the form with your **Name**, **First Name**, **Town** and **Zip Code**. You can ignore the other field and click on **accept**.
7. Go to your **Groups** parameters on the top right ![group_selection_ifb](/Users/laurent/Documents/formations/2020_08_UNIX/img/group_selection_ifb.png)
8. Click on ![join_a_group](/Users/laurent/Documents/formations/2020_08_UNIX/img/join_a_group.png) and type **LBMC Unix 2020**
9. You can click on the **+** sign to candidate and wait to be accepted in the group
7. Go to your **Groups** parameters on the top right ![group_selection_ifb](./img/group_selection_ifb.png)
8. Click on ![join_a_group](./img/join_a_group.png) and type **CAN UNIX 2023**
9. You can click on the **+** sign to register and wait to be accepted in the group
## Starting the LBMC Unix 2020 appliance
## Starting the LBMC Unix 2022 appliance
To follow this practical you will need to start the **[LBMC Unix 2020](https://biosphere.france-bioinformatique.fr/catalogue/appliance/177/) ** appliance from the [IFB Cloud](https://biosphere.france-bioinformatique.fr/) and click on the ![start](/Users/laurent/Documents/formations/2020_08_UNIX/img/start_VM.png) button after login with your account.
To follow this practical you will need to start the **[LBMC Unix 2022](https://biosphere.france-bioinformatique.fr/catalogue/appliance/177/)** appliance from the [IFB Cloud](https://biosphere.france-bioinformatique.fr/) and click on the ![start](./img/start_VM.png) button after login with your account.
In the IFB jargon, appliance means **virtual machine** (VM). Remember how an universal Turing machine can run any programs ? A virtual machine, is a simulation program, simulating a physical computer. VM's have the following advantages:
In the IFB jargon, appliance means **virtual machine** (VM). Remember how a universal Turing machine can run any programs ? A virtual machine, is a simulation program, simulating a physical computer. VM's have the following advantages:
- Copies of the VM will be identical (there will be no differences between your running *LBMC Unix 2020 appliance* and mine )
- Upon start the VM is reset to the *LBMC Unix 2020 appliance* state
- You can break everything in your VM, terminate it and start a new one
- Copies of the VM will be identical (there will be no differences between your running *LBMC Unix 2022 appliance* and mine )
- Upon starting the VM is reset to the *LBMC Unix 2022 appliance* state
- You can break everything in your VM, terminate it and start a new one.
To access to your appliance you can go to the [**myVM** tab](https://biosphere.france-bioinformatique.fr/cloud/)
![myVM tab](/Users/laurent/Documents/formations/2020_08_UNIX/img/my_VM_ifb.png)
![myVM tab](./img/my_VM_ifb.png)
You will see the list of your running or starting appliances
You will see the list of your running or starting appliances.
![my appliances](/Users/laurent/Documents/formations/2020_08_UNIX/img/my_appliances_ifb.png)
![my appliances](./img/my_appliances_ifb.png)
**Don't forget to terminate your appliances at the end of the session by clicking on** ![rm my appliances ifb](/Users/laurent/Documents/formations/2020_08_UNIX/img/rm_my_appliances_ifb.png)
**Don't forget to terminate your appliances at the end of the session by clicking on** ![rm my appliances ifb.](./img/rm_my_appliances_ifb.png)
You will need to start this appliance at the start of each session of this course and terminate it afterward.
The ![hourlass](/Users/laurent/Documents/formations/2020_08_UNIX/img/wait_my_appliances_ifb.png) symbol indicate that your appliance is starting.
The ![hourglass](./img/wait_my_appliances_ifb.png) symbol indicates that your appliance is starting.
## Accessing the LBMC Unix 2020
## Accessing the LBMC Unix 2022
You can open the **https** link next to the termination button of your appliance in a new tab. You will have the following message
![ssl warning](/Users/laurent/Documents/formations/2020_08_UNIX/img/ssl_warning.png)
![ssl warning](./img/ssl_warning.png)
This mean that the https connection is encrypted with a certificate unknown to your browser. As this certificate is going to be destroyed when you terminate your appliance, we don't want to pay a certification authority to validate it. Therefore you can safely add an exception for this certificate.
This means that the https connection is encrypted with a certificate unknown to your browser. As this certificate is going to be destroyed when you terminate your appliance, we don't want to pay a certification authority to validate it. Therefore you can safely add an exception for this certificate.
![ssl exception](/Users/laurent/Documents/formations/2020_08_UNIX/img/ssl_exception.png)
![ssl exception](./img/ssl_exception.png)
......@@ -71,7 +74,7 @@ The webpage you will load will display only the following line:
achinea3e18205-1f8c-4ee1-995e-d33ef57afa3c login:
```
To get your identifiant you can click on the **Params** next to the **https** link.
To get your identification information you can click on the **Params** next to the **https** link.
**The password and the https links are one of the only things that going to change when you start a new appliance.**
......@@ -81,12 +84,12 @@ Password:
To copy / paste your password, you will need to perform a right click and select **past from browser**
To copy / paste your password, you will need to perform a right-click and select **past from the browser.**
![past from browser](/Users/laurent/Documents/formations/2020_08_UNIX/img/shellinabox_past_from_browser.png)
![past from browser](./img/shellinabox_past_from_browser.png)
Then paste your password in the dialog box.
Don't worry the password will not be displayed (not even in the form of `*****`, so someone looking at your screen will not be able to guess it's length), you can press **enter** to log on your VM.
[first steps in a terminal.](http://perso.ens-lyon.fr/laurent.modolo/unix/3_first_steps_in_a_terminal.html)
\ No newline at end of file
[First steps in a terminal.](./3_first_steps_in_a_terminal.html)
---
title: First step in a terminal
author: "Laurent Modolo"
---
# First step in a terminal
```{r include = FALSE}
if (!require("fontawesome")) {
install.packages("fontawesome")
}
library(fontawesome)
knitr::opts_chunk$set(echo = TRUE)
knitr::opts_chunk$set(comment = NA)
```
[![cc_by_sa](./img/cc_by_sa.png)](http://creativecommons.org/licenses/by-sa/4.0/)
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" />
</a>
Objective: learn to use basic terminal command
Congratulation you are now connected on your VM !
Congratulations you are now connected on your VM !
The first thing that you can see is a welcome message (yes GNU/Linux users are polite and friendly), and information on your distribution.
......@@ -16,36 +26,37 @@ The first thing that you can see is a welcome message (yes GNU/Linux users are p
What is the distribution installed on your VM ?
You can go to this distribution website and have a look at the liste of firm using it.
You can go to this distribution website and have a look at the list of firms using it.
## Shell
A command-line interpreter (or shell), is a software designed to read lines of text entered by a user to interact with an OS.
To simplify the shell execute the following infinite loop:
To simplify the shell executes the following infinite loop:
1. read a line
2. translate this line as a program execution with it's parameters
2. translate this line as a program execution with its parameters
3. launch the corresponding program with the parameters
3. wait for the program to finish
4. Go back to 1.
When you open a terminal on an Unix like OS, you will have a **prompt** displayed: it can end with a **$** or a **%** caracter depending on your configuration. As long as you see your prompt, it means that you are in step **1.**, if no prompt is visible, you are in step **4.** or you have set up a very minimalist configuration for your shell.
When you open a terminal on an Unix-like OS, you will have a **prompt** displayed: it can end with a `$` or a `%` character depending on your configuration. As long as you see your prompt, it means that you are in step **1.**, if no prompt is visible, you are in step **4.** or you have set up a very minimalist configuration for your shell.
<img src="./img/prompt.png" alt="prompt" style="zoom:150%;" />
The blinking square or vertical bar represent your **cursor**. Shell predate graphical interfaces, so most of the time you won't be able to move this cursor with your mouse, but with the directional arrows (left and right).
The blinking square or vertical bar represents your **cursor**. Shell predates graphical interfaces, so most of the time you wont be able to move this cursor with your mouse, but with the **directional arrows** (left and right).
On the IFB, your prompt is a **$**
On the IFB, your prompt is a `$`:
```sh
etudiant@VM:~$
```
You can identify the following information form your prompt: **etudiant** is your login and **VM** is the name of your VM (**~** is where you are on the computer, but we will come back to that later).
You can identify the following information from your prompt: **etudiant** is your login and **VM** is the name of your VM (`~` is where you are on the computer, i.e. the current working directory, but we will come back to that later).
On Ubuntu 20.04, the default shell is [Bash](https://en.wikipedia.org/wiki/Bash_(Unix_shell)) while on recent version of macOS it's [zsh](https://en.wikipedia.org/wiki/Z_shell). There are [many different shell](https://en.wikipedia.org/wiki/List_of_command-line_interpreters), for example, Ubuntu 20.04 also have [sh](https://en.wikipedia.org/wiki/Bourne_shell) installed.
On Ubuntu 20.04, the default shell is [Bash](https://en.wikipedia.org/wiki/Bash_(Unix_shell)) while on recent version of macOS its [zsh](https://en.wikipedia.org/wiki/Z_shell). There are [many different shell](https://en.wikipedia.org/wiki/List_of_command-line_interpreters), for example, Ubuntu 20.04 also has [sh](https://en.wikipedia.org/wiki/Bourne_shell) installed.
## Launching programs
## Launching Programs
You can launch every program present on your computer from the shell. The syntax will always be the following:
......@@ -55,7 +66,7 @@ etudiant@VM:~$ program_name option_a option_b option_c [...] option_n
And pressing **enter** to execute your command.
For example we can launch the `cal` software by typing the following command and pressing **enter**:
For example, we can launch the `cal` software by typing the following command and pressing **enter**:
```sh
cal
......@@ -63,29 +74,29 @@ cal
When you launch a command, various things can happen:
- Information can be diplayed in the shell
- Information can be displayed in the shell
- Computation can be made
- Files can we read or written
- etc.
We can pass argument to the `cal` software the following way
We can pass argument to the `cal` software the following way.
```sh
cal -N
cal -3
```
What is the effect of the `-N` parameter ?
What is the effect of the `-3` parameter ?
You can add as many parameters as you want to your command, try `-N -C` what is the meaning of the `-C` parameter ?
You can add as many parameters as you want to your command, try `-3 -1` what is the meaning of the `-1` parameter ?
The `-H` option display the month of a given date in a `yyyy-mm-dd` format. Try to display your month of birth in vertical format.
The `-d` option display the month of a given date in a `yyyy-mm` format. Try to display your month of birth.
Traditionally, parameters are *named* which mean that they are in the form of:
Traditionally, parameters are *named* which means that they are in the form of:
* `-X` for an on/off option (like `cal -N`)
* `-X something` for an input option (like `cal -H yyyy-mm-dd`)
* `-X` for an on/off option (like `cal -3`)
* `-X something` for an input option (like `cal -d yyyy-mm`)
Here the name of the paremeter is `X`, but software can also accept list of unamed parameter. Try the following:
Here the name of the parameter is `X`, but software can also accept list of unnamed parameters. Try the following:
```sh
cal 2
......@@ -97,9 +108,9 @@ What is the difference for the parameter value `2` in the first and third comman
## Moving around
For the `cal` program, the position in the file system is not important (it's not going to change the calendar). However, for most tools that are able to read or write files, it's important to know where you are. This is the first real difficulty with command line interface: you need to remember where you are.
For the `cal` program, the position in the file system is not important (its not going to change the calendar). However, for most tools that are able to read or write files, its important to know where you are. This is the first real difficulty with command line interface: you need to remember where you are.
If you are lost you can **p**rint your **w**orking **d**irectory (i.e. where you are now, working) with the command
If you are lost, you can **p**rint your **w**orking **d**irectory (i.e., where you are now, working) with the command.
```sh
pwd
......@@ -107,7 +118,7 @@ pwd
Like `cal`, the `pwd` command return textual information
By default when you log on an Unix system you are in your **HOME** directory. Every user (except one) should have it's home directory in the `/home/`folder.
By default when you log on an Unix system, you are in your **HOME** directory. Every user (except one) should have its home directory in the `/home/`folder.
To **c**hange **d**irectory you can type the command `cd`, `cd` take one argument: the path of the directory where you want to go. go to the `/home` directory.
......@@ -117,37 +128,37 @@ cd /home
The `cd` command don't return any textual information, but change the environement of the shell (you can confirm it with ` pwd`) ! You can also see this change in your prompt:
The `cd` command doesn’t return any textual information, but change the environment of the shell (you can confirm it with ` pwd`) ! You can also see this change in your prompt:
```sh
`etudiant@VM:/home$`
```
What happend when you type `cd` without any argument ?
What happens when you type `cd` without any argument ?
What is the location shown in your prompt ? Is it coerent with the `pwd` information ? Can you `cd` to the `pwd` path ?
What is the location shown in your prompt ? Is it coherent with the `pwd` information ? Can you `cd` to the `pwd` path ?
When we move around a file system, we often want to see what is in a given folde. We want to **l**i**s**t the directory content. Go back to the `/home` directory and use to the `ls` command see how many have a home directory there.
When we move around a file system, we often want to see what is in a given folder. We want to **l**i**s**t the directory content. Go back to the `/home` directory and use to the `ls` command see how many people have a home directory there.
We will see various option of the `ls` command, throughout this course. Try the `-a` option.
We will see various options for the `ls` command, throughout this course. Try the `-a` option.
```sh
ls -a
```
What changed commpared to the `ls` command without this option ?
What changed compared to the `ls` command without this option ?
Go to your home folder with the bare `cd` command and run the `ls -a` command again. The `-a` option make the `ls` command list hidden files and folders. On Unix systems, hidden files and folders are every files and folders whose name start with a "**.**".
Go to your home folder with the bare `cd` command and run the `ls -a` command again. The `-a` option makes the `ls` command list hidden files and folders. On Unix systems, hidden files and folders are all files and folders whose name starts with a `.`.
Can you `cd` to "**.*" ?
Can you `cd` to `.` ?
```sh
cd .
```
What happend ?
What happened ?
Can you cd to "**..**" ?
Can you cd to `..` ?
```sh
cd ..
......@@ -155,33 +166,17 @@ cd ..
What appended ?
Repeat 3 times the previous command (you can use the upper directionnal arrow to repeat the last command).
Repeat 3 times the previous command (you can use the upper directional arrow to repeat the last command).
What append ?
You can use the `-l` option in combinaison with the `-a` option to know more about those folder.
## Unix file system structure
You can use the `-l` option in combination with the `-a` option to know more about those folders.
> On a UNIX system, everything is a file ; if something is not a file, it is a process.
> We have seen the commands :
>
> Machtelt Garrels
The followings are files:
- a text file
- an executable file
- a folder
- a keyboard
- a disk
- an usb key
- ...
This mean that your keyboard is represented as a file within the OS.
This file system is organized as a tree. As you have seen every folder has a parent folder exept the `/` folder whose parent is itself.
Every file can be accessed by an **absolute path** starting at the root. Your user home folder can be accessed with the path `/home/etudiant/`. Go to your user home folder.
We can also access file with a **relative path**, using the special folder "**..**". From your home folder, go to the *ubuntu* user home folder without passing by the root (we will see use of the "**.**" folder later).
> - `cal` for calendar
> - `cd` for change directory
> - `ls` for list directory
> - `pwd` for print working directory
[You can now go to the Unix file system.](./4_unix_file_system.html)
---
title: GNU/Linux file system
author: "Laurent Modolo"
---
```{r include = FALSE}
if (!require("fontawesome")) {
install.packages("fontawesome")
}
library(fontawesome)
knitr::opts_chunk$set(echo = TRUE)
knitr::opts_chunk$set(comment = NA)
```
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" />
</a>
Objective: Understand how files are organized in Unix
> On a UNIX system, everything is a file ; if something is not a file, it is a process.
>
> Machtelt Garrels
The followings are files:
- a text file
- an executable file
- a folder
- a keyboard
- a disk
- a USB key
- ...
This means that your keyboard is represented as a file within the OS.
This file system is organized as a tree. As you have seen, every folder has a parent folder except the `/` folder whose parent is itself.
Every file can be accessed by an **absolute path** starting at the root. Your user home folder can be accessed with the path `/home/etudiant/`. Go to your user home folder.
We can also access files with a **relative path**, using the special folder `..`. From your home folder, go to the *ubuntu* user home folder without passing by the root (we will see use of the `.` folder later).
## File Types
As you may have guessed, every file type is not the same. We have already seen that common file and folder are different. Here is the list of file types:
- `-` common files
- `d` folders
- `l` links
- `b` disk
- `c` special files
- `s` socket
- `p` named pipes
To see the file type you can type the command
```sh
ls -la
```
The first column will tell you the type of the file (here we have only the type `-` and `d`). We will come back on the other information later. Another less used command to get fine technical information on a file is the command `stat [file_name]`. Can you get the same information as `ls -la` with `stat` ?
## Common Structure
From the root of the system (`/`), most of the Unix-like distribution will share the same folder tree structure. On macOS, the names will be different because when you sell the most advanced system in the world you need to rename things, with more advanced names.
### `/home`
You already know this one. You will find all your file and your configuration files here. Which configuration file can you identify in your home ?
### `/boot`
You can find the Linux kernel and the boot manager there. What is the name of your boot manager (process by elimination) ?
You can see a new type of file here, the type `l`. What it the version of the **vmlinuz** kernel ?
### `/root`
The home directory of the super user, also called root (we will go back on him later). Can you check its configuration file ?
### `/bin`, `/sbin`, `/usr/bin` and `/opt`
The folder containing the programs used by the system and its users. Programs are simple file readable by a computer, these files are often in **bin**ary format which means that it’s extremely difficult for a human to read them.
What is the difference between `/bin` and `/usr/bin` ?
`/sbin` stand for system binary. What are the names of the programs to power off and restart your system ?
`/opt` is where you will find the installation of non-conventional programs (if you don’t follow [the guide of good practice of the LBMC](http://www.ens-lyon.fr/LBMC/intranet/services-communs/pole-bioinformatique/ressources/good_practice_LBMC), you can put your bioinformatics tools with crapy installation procedure there).
### `/lib` and `/usr/lib`
Those folder contains system libraries. Libraries are a collection of pieces of codes usable by programs.
What is the difference between `/lib` and `/usr/lib`.
Search information on the `/lib/gnupg` library on the net.
### `/etc`
The place where system configuration file and default configuration file are. What is the name of the default configuration file for `bash` ?
### `/dev`
Contains every peripheric
What is the type of the file `stdout` (you will have to follow the links)?
With the command `ls -l` can you identify files of type `b` ?
Using `less` can you visualize the content of the file `urandom` ? What about the file `random` ?
What is the content of `/dev/null`?
### `/var`
Storage space for variables and temporary files, like system logs, locks, or file waiting to be printed...
In the file `auth.log` you can see the creation of the `ubuntu` and `etudiant `account. To visualize a file you can use the command
```sh
less [file_path]
```
You can navigate the file with the navigation arrows. Which group the user `ubuntu` belongs to that the user `etudiant`don’t ?
To close the `less` you can press `Q`. Try the opposite of `less`, what are the differences ?
What is the type of the file `autofs.fifo-var-autofs-ifb` in the `run` folder ? From **fifo** in the name, can you guess the function of the `p` file ?
There are few examples of the last type of file in the `run` folder, in which color the command `ls -l` color them ?
### `/tmp`
Temporary space. **Erased at each shutdown of the system !**
### `/proc`
Information on the system resources. This file system is virtual. What do we mean by that ?
One of the columns of the command `ls -l` show the size of the files. Try is on the `/etc` folder. You can add the `-h` option to have human readable file size.
What are the sizes of the files in the `/proc` folder ?
From the `cpuinfo` file get the brand of the cpu simulated by your VM.
From the `meminfo` file retrieve the total size of RAM
## Links
With the command `ls -l` we have seen some links, the command `stat` can give us more information on them
```sh
stat /var/run
```
What is the kind of link for `/var/run` ?
Most of the time, when you are going to work with links, you will work with this kind of link. You can create a **l**i**n**k with the command `ln` and the option `-s` for a **s**ymbolic.
The first argument after the option of the `ln` command is the target of the link, the second argument is the link itself:
```sh
cd
ln -s .bash_history bash_history_slink
ls -la
```
What are the differences between the two following commands ?
```sh
stat bash_history_slink
stat .bash_history
```
Symbolic links can bridge across, file system, if the target of the link disappears the link will be broken.
You can delete a file with the command `rm`
**There is no trash with the command `rm` double-check your command before pressing enter !**
Delete your `.bash_history` file, what happened to the `bash_history_slink` ?
The command `ln` without the `-s` option create hard links. Try the following commands:
```sh
stat .bashrc
ln .bashrc bashrc_linka
stat .bashrc
ln .bashrc bashrc_linkb
```
Use `stat` to also study `bashrc_linka` and `bashrc_linkb`.
What happens when you delete `bashrc_linka` ?
To understand the notion of **Inode** we need to know more about storage systems.
## Disk and partition
On a computer, the data are physically stored on a media (HDD, SSD, USB key, punch card...)
![IBM_card_storage_NARA](./img/IBM_card_storage_NARA.jpg)
(Punched cards in storage at a U.S. Federal records center in 1959. All the data visible here would fit on a 4 GB flash drive.)
You cannot dump data directly into the disk, you need to organize things to be able to find them back.
![disk](./img/disk.png)
Each media is divided into partitions:
![partitions](./img/partition.png)
The media is divided into one or many partition, each of which have a file system type. Examples of file system types are
- fat32, exFAT
- ext3, ext4
- HFS+
- NTFS
- ...
The file system handle the physical position of each file on the media. The position of the file in the index of file is called **Inode**.
The action of attaching a given media to the Unix file system tree, is called mounting a partition or media. To have a complete list of information on what is mounted where, you can use the `mount `command without argument.
```sh
mount
```
Find which disk is mounted at the root of the file tree.
> We have seen the commands:
>
> - `stat` to display information on a file
> - `less` to visualize the content of a file
> - `ln` to create links
> - `mount` to list mount points
[That’s all for the Unix file system, we will come back to it from time to time but for now you can head to the next section.](./5_users_and_rights.html)
---
title: Users and rights
author: "Laurent Modolo"
---
```{r include = FALSE}
if (!require("fontawesome")) {
install.packages("fontawesome")
}
library(fontawesome)
knitr::opts_chunk$set(echo = TRUE)
knitr::opts_chunk$set(comment = NA)
```
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" />
</a>
Objective: Understand how rights works in GNU/Linux
GNU/Linux and other Unix-like OS are multiuser, this means that they are designed to work with multiple users connected simultaneously to the same computer.
There is always at least one user: the **root** user
- It’s the super user
- he has every right (we can say that he ignores the rights system)
- this account should only be used to administer the system.
There can also be other users who
- have rights
- belong to groups
- the groups also have rights
## File rights
Each file is associated with a set of rights:
- `-` nothing
- `r` **r**eading right
- `w` **w**riting right
- `x` e**x**ecution right
Check your set of rights on your `.bashrc` file
```sh
ls -l ~/.bashrc
```
The first column of the `ls -l` output shows the status of the rights on the file
![user_rights](./img/user_right.png)
```
rwxr-xr--
\ /\ /\ /
v v v
| | others (o)
| |
| group (g)
|
user (u)
```
- the 1st character is the type of the file (we already know this one)
- he 3 following characters (2 to 4) are the **user** rights on the file
- the characters 5 to 7 are the **group** rights on the file
- the characters 8 to 10 are the **others’** rights on the file (anyone not the **user** nor in the **group**)
To change the file rights you can use the command `chmod`
Use the command `ls -l` to check the effect of the following options for `chmod`
```sh
chmod u+x .bashrc
```
```sh
chmod g=rw .bashrc
```
```sh
chmod o+r .bashrc
```
```sh
chmod u-x,g-w,o= .bashrc
```
What can you conclude on the symbols `+` , `=`, `-` and `,` with the `chmod` command ?
> ### Numeric notation
>
> Another method for representing Unix permissions is an [octal](https://en.wikipedia.org/wiki/Octal) (base-8) notation as shown by `stat -c %a`.
>
> | Symbolic notation | Numeric notation | English |
> | ------------------ | ----------------- | ------------------------------------------------------------ |
> | `----------` | 0000 | no permissions |
> | `-rwx------` | 0700 | **read, write, & execute only for owner** |
> | `-rwxrwx---` | 0770 | read, write, & execute for owner and group |
> | `-rwxrwxrwx` | 0777 | read, write, & execute for owner, group and others |
> | `---x--x--x` | 0111 | execute |
> | `--w--w--w-` | 0222 | write |
> | `--wx-wx-wx` | 0333 | write & execute |
> | `-r--r--r--` | 0444 | read |
> | `-r-xr-xr-x` | 0555 | read & execute |
> | `-rw-rw-rw-` | 0666 | read & write |
> | `-rwxr-----` | 0740 | owner can read, write, & execute; group can only read; others have no permission |
The default group of your user is the first in the list of the groups you belong to. You can use the command `groups` to display this list. What is your default group ?
The command `id` show the same information, but with some differences what are they ?
Can you cross this additional information with the content of the file `/etc/passwd` and `/etc/group` ?
What is the user *id* of **root** ?
When you create an empty file, system default rights and your default groups are used. You can use the command `touch` to create a file.
```sh
touch my_first_file.txt
```
What are the default rights when you crate a file ?
You can create folders with the command `mkdir` (**m**a**k**e **dir**ectories).
```sh
mkdir my_first_dir
```
What are the default rights when you create a directory ? Try to remove the execution rights, what appends then ?
You can see the **/root** home directory. Can you see it’s content ? Why ?
Create a symbolic link (`ln -s`) to your **.bashrc** file, what are the default rights to symbolic links ?
Can you remove the writing right of this link ? What happened ?
## Users and Groups
We have seen how to change the right associated with the group, but what about changing the group itself ? The command `chgrp` allows you to do just that:
```sh
chgrp audio .bashrc
```
Now the next step is to change the owner of a file, you can use the command `chown` for that.
```sh
chown ubuntu my_first_file.txt
```
You can change the user and the group with this command:
```sh
chown ubuntu:audio my_first_file.txt
```
What are the rights on the program `mkdir` (the command `which` can help you find where program file are) ?
Can you remove the execution rights for the others ?
The command `cp` allows you to **c**o**p**y file from one destination to another.
```sh
man cp
```
Copy the `mkdir` tool to your home directory. Can you remove execution rights for the others on your copy of `mkdir` ? Can you read the contentof the `mkdir` file ?
You cannot change the owner of a file, but you can always allow another user to copy it and change the rights on its copy.
## Getting admin access
Currently you don’t have administrative access to your VM, this means that you don’t have the password to the *root* account. Another way to get administrative access in Linux is to use the `sudo` command.
You can read the documentation (manual) of the `sudo` command with the command `man`
```sh
man sudo
```
Like for the command, `less` you can close `man` by pressing **Q**.
![sandwich](https://imgs.xkcd.com/comics/sandwich.png)
On Ubuntu, only members of the group **sudo** can use the `sudo` command. Are you in this group ?
**The root user can do everything in your VM, for example it can delete everything from the `/` directory but it’s not a good idea (see the [Peter Parker principle](https://en.wikipedia.org/wiki/With_great_power_comes_great_responsibility))**
One advantage of using a command line interface is that you can easily reuse command written by others. Copy and paste the following command in your terminal to add yourself in the **sudo** group.
```sh
docker run -it --volume /:/root/chroot alpine sh -c "chroot /root/chroot /bin/bash -c 'usermod -a -G sudo etudiant'"
```
We will come back to this command later in this course when we talk about virtualisation.
You have to logout and login to update your list of groups. To logout from a terminal, you can type `exit` or press **ctrl** + **d**.
Check your user information with the `sudo` command
```sh
sudo id
```
You can try again the `chown` command with the `sudo` command.
Check the content of the file `/etc/shadow` , what is the utility of this file (you can get help from the `man` command).
## Creating Users
You can add a new user to your system with the command `useradd`
```sh
useradd -m -s /bin/bash -g users -G adm,docker student
```
- `-m` create a home directory
- `-s` specify the shell to use
- `-g` the default group
- `-G` the additional groups
To log into another account you can use the command `su`
What is the difference between the two following commands ?
```sh
su student
```
```sh
sudo su student
```
What append when you don't specify a login with the `su` command ?
## Creating groups
You can add new groups to your system with the command `groupadd`
```sh
sudo groupadd dummy
```
Then you can add users to this group with the command `usermod`
```sh
sudo usermod -a -G dummy student
```
And check the result:
```sh
groups student
```
To remove an user from a group you can rewrite its list of groups with the command `usermod`
```sh
sudo usermod -G student student
```
Check the results.
## Security-Enhanced Linux
While what you have seen in this section hold true for every Unix system, additional rules can be applied to control the rights in Linux. This is what is called [SE Linux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux) (**s**ecurity-**e**nhanced **Linux**)
When SE Linux is enabled on a system, every **process** can be assigned a set of rights. This is how, on Android for example, some programs can access your GPS while others cannot, etc. In this case it's not the user rights that prevail, but the **process** launched by the user.
> We have seen the commands:
>
> - `chmod` to change rights
> - `touch` to create an empty file
> - `mkdir` to create a directory
> - `chgrp` to change associated group
> - `chown` to change owner
> - `man` to display the manual
> - `cp` to copy files
> - `sudo` to borrow **root** rights
> - `groupadd` to create groups
> - `groups` to list groups
> - `usermod`to manipulate users' groups
[To understand more about processes you can head to the next section.](./6_unix_processes.html)
---
title: Unix Processes
author: "Laurent Modolo"
---
```{r include = FALSE}
if (!require("fontawesome")) {
install.packages("fontawesome")
}
library(fontawesome)
knitr::opts_chunk$set(echo = TRUE)
knitr::opts_chunk$set(comment = NA)
```
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" />
</a>
Objective: Understand how process works in GNU/Linux
A program is a list of instructions to be executed on a computer. These instructions are written in one or many files in a format readable by the computer (binary files), or interpretable by the computer (text file). The interpretable format needs to be processed by an interpreter who is in binary format.
The execution of a program on the system is represented as one or many processes. The program is the file of instruction while the process is the instructions being read.
`mkdir` is the program, when you type `mkdir my_folder`, you launch a `mkdir` process.
Your shell is a process to manipulate other processes.
> In multitasking operating systems, processes (running programs) need a way to create new processes, e.g., to run other programs. [Fork](https://en.wikipedia.org/wiki/Fork_(system_call)) and its variants are typically the only way of doing so in Unix-like systems. For a process to start the execution of a different program, it first forks to create a copy of itself. Then, the copy, called the "[child process](https://en.wikipedia.org/wiki/Child_process)", calls the [exec](https://en.wikipedia.org/wiki/Exec_(system_call)) system call to overlay itself with the other program: it ceases execution of its former program in favor of the other.
Some commands in your shell don’t have an associated process, for example there is no `cd` program, it’s a functionality of your shell. The `cd` command tell your `bash` process to do something not to fork another process.
## Process attributes
- **PID** : the **p**rocess **id**entifier is an integer, at a given time each **PID** is unique to a process
- **PPID** : the **p**arent **p**rocess **id**entifier is the **PID** of the process that has stared the current process
- **UID** : the **u**ser **id**entifier is the identifier of the user that has started the process, except for SE Linux, the process will have the same right as the user launching it.
- **PGID** : the **p**rocess **g**roup **id**entifier (like users, processes have groups)
You can use the command `ps` to see the processes launched by your user.
```sh
ps
```
Like for the command, `ls` you can use the switch `-l` to have more details.
Open another tab in your browser to log again on your VM. Keep these tabs open, we are going to use both of them in this session.
In this new tab, you are going to launch a `less` process.
```sh
less .bashrc
```
Come back, to your first tab, can you see your `less` process with the command `ps` ?
The `ps` option `-u [login]` list all the processes with **UID** the **UID** associated with `[login]`
```sh
ps -l -u etudiant
```
Is the number of `bash` processes consistent with the number of tabs you opened ?
What is the **PPID** of the `less` process ? Can you identify in which `bash` process `less` is running ?
Did you launch the `systemd` and `(sd-pam)` process ?
**pam** stands for [**p**luggable **a**uthentication **m**odules](https://www.linux.com/news/understanding-pam/), it’s a collection of tools that handle identification and resource access restriction. From the **PPID** of the `(sd-pam)` can you find which process launched `(sd-pam)` ? What is the **PPID** of this process ?
The option `-C` allows you to filter process by name
```sh
ps -l -C systemd
```
Who launched the first `systemd` process ?
## Processes tree
From **PPID** to **PPID**, you can guess that like the file system, processes are organized in a tree. The command `pstree` can give you a nice representation of this tree.
The following `ps` command shows information on the process with **PID 1**
```sh
ps -l -1
```
Is this output coherent with what you know on **PID** and the previous `ps` command ? Can you look at the corresponding program (with the command `which`) ?
Can you look for information on **PID 0** ?
The root of the processes tree is the **PID 1**.
What is the **UID** of the `dockerd` process, can you guess why we were able to gain `sudo` access in the previous section by using a `docker` command ?
`ps` give you a static snapshot of the processes but processes are dynamic. To see them running you can use the command `top`. While `top` is functional, most systems have `htop` with a more accessible interface. You can test `top` and `htop`.
Like `ps` you can use `-u etduiant` with htop to only display your user processes.
With the `F6` key, you can change the column on which to sort your process.
- Which process is consuming the most of CPU ?
- Which process is consuming the most of memory ?
What is the difference between `M_SIZE` (`VIRT` column), `M_RESIDENT` (`RES` column) and `M_SHARE` (`SHR` column) ? To which value, the column `MEM%` corresponds to ?
- `M_SIZE` : The total amount of virtual memory used by the task. It includes all code, data and shared libraries plus pages that have been swapped out and pages that have been mapped but not used (if an application requests 1 GB of memory but uses only 1 MB, then `VIRT` will report 1 GB).
- `M_RESIDENT` : what’s currently in the physical memory. This does not include the swapped out memory and some of the memory may be shared with other processes (If a process uses 1 GB of memory and it calls `fork()`, the result of forking will be two processes whose `RES` is both 1 GB but only 1 GB will actually be used since Linux uses copy-on-write).
- `M_SHARE` : The amount of shared memory used by a task. It simply reflects memory that could be potentially shared with other processes.
Wait what is swapped out memory ?
> Linux divides its physical RAM (random access memory) into chucks of memory called pages. Swapping is the process whereby a page of memory is copied to the preconfigured space on the hard disk, called swap space, to free up that page of memory. The combined sizes of the physical memory and the swap space is the amount of virtual memory available.
And as your HDD (even your fast SSD) is way slower than your RAM, when you run out of RAM and the system start to swap out memory, things will start to go really slowly on your computer. Generally, you want to avoid swapping. The swap space is often a dedicated partition in the *Linux_swap* format.
From the `htop` command, what is the size of the swap space on your VM ?
You have control over all the process launched with your UID. To test this control we are going to use the well-named command `stress`. Check the **man**ual of the `stress` command.
Launch the `stress` for 1 CPU and 3600 second.
You don’t have a prompt, it means that the last command (`stress`) is running.
## Terminate
Instead of taking a nap and come back at the end of this session, we may want to interrupt this command. The first way to do that is to ask the system to terminate the `stress` process.
From your terminal you can press `ctrl` + `c`. This short cut terminates the current process, it works everywhere except for programs like `man` or `less` which can be closed with the key `q`.
Launch another long `stress` process and switch to your other terminal tab, then, list your active process.
```sh
ps -l -u etudiant
```
You ask `stress` to launch a worker using 100% of one CPU (you can also see that with `htop`). You can see that the `stress` process you launched (with the PPID of your `bash`) forked another `stress` process.
Another way to terminate a process is with the command `kill`. `kill` is used to send a signal to a process with the command:
```sh
kill -15 PID
```
The `-15` option is the default option for `kill` so you can also write `kill PID`.
We can do the same thing as with the command `ctrl` + `c`: ask nicely the process to terminate itself. The `-15` signal is called the **SIGTERM**.
> On rare occasions a buggy process will not be able to listen to signals anymore. The signal `-9` will kill a process (not nicely at all). The `-9` signal is called the **SIGKILL** signal. There are 64 different signals that you can send with the `kill` command.
Use the `kill` command to terminate the worker process of your stress command. Go to the other tab where stress was running. What is the difference with your previous `ctrl` + `c` ?
In your current terminal type the `bash` command, nothing happens. You have a shell within a shell. Launch a long `stress` command and switch to the other tab.
You can use the `ps` command to check that `sleep` is running within a `bash` within a `bash`
```sh
ps -l --forest -u etudiant
```
Nicely terminate the intermediate `bash`. What happened ?
Try not nicely. What happened ?
A process with a **PPID** of **1** is called a **daemon**, daemons are processes that run in the background. Congratulations you created your first daemon.
Kill the remaining `stress `processes with the command `pkill`. You can check the **man**ual on how to do that.
## Suspend
Launch `htop` then press `ctrl` + `z`. What happened ?
```sh
ps -l -u etudiant
```
The manual of the `ps` command say the following about process state
```
D uninterruptible sleep (usually IO)
I Idle kernel thread
R running or runnable (on run queue)
S interruptible sleep (waiting for an event to complete)
T stopped by job control signal
t stopped by debugger during the tracing
W paging (not valid since the 2.6.xx kernel)
X dead (should never be seen)
Z defunct ("zombie") process, terminated but not reaped by its parent
```
You can use the command `fg` to put `htop` in the **f**ore**g**round.
Close `htop` and type twice the following command (`-i 1` is for simulating **io** **i**nput **o**utput operations) :
```sh
stress -i 1 -t 3600 &
```
Type the command `jobs`. What do you see ? You can specify which `stress` process you want to bring to the foreground with the command `fg %N` with `N` the number of the job.
```sh
fg %2
```
Bring the 2nd `htop` to the foreground. Put it back to the background with `ctrl` + `z`. What is now the differences between your two `stress` processes ?
The command `bg` allows you to resume a job stopped in the background. You can restart your stopped `stress` process with this command. You can use the `kill %N` syntax to kill your two `stress` processes.
## Priority
We have seen that we can launch a `stress `process to use 100% of a CPU. Launch two `stress` processes like that in the background.
What happened ? What can you see with the `htop` command ?
> In Linux the [Scheduler](https://en.wikipedia.org/wiki/Completely_Fair_Scheduler), is a system process that manages the order of execution of the task by the CPU(s). Linux and most Unix systems are also multiprocessors OS which means that your OS is constantly switching between process that has access to the CPU(s). From a universal Turing machine point of view, the head of the machine would be constantly switching back and forth on the tape.
You are working on a computer with a graphical interface, think about the processes drawing your windows, the processes reading and rendering your mouse, checking for your mail, loading and rendering your web pages, reading your keystrokes to send them back over the network to the NSA. The scheduler of your OS has to jungle between everything’s without losing anything (don’t be too hard on the windows OS).
The **nice** state of a process indicates it’s priority for the scheduler. **nice** value ranges from **-20** (the highest priority) to **19** (the lowest priority). The default **nice** value is **0**. The command `renice` allows you to change the **nice** value of a process:
```sh
renice -n N -p PID
```
With `N` the **nice** value.
Use `renice` to set the **nice** value of the first `stress` process worker to **19**. Use the command `htop` to check the result.
Can we increase the difference between the two processes ? Use re renice command to set the **nice** value of the second `stress` process worker to **-20**. What happened ?
Only the *root* user can lower the **nice** value of a process. You can also start start a new process with a given **nice** value with the command `nice`:
```sh
nice -n 10 stress -c 1 -t 3600 &
```
Without root access you can only set value greater than 0.
> We have seen the commands:
>
> - `ps` to display processes
> - `pstree` to display a tree of processes
> - `which` to display the PATH of a program
> - `top`/`htop` for a dynamic view of processes
> - `stress` to stress your system
> - `kill`/`pkill` to stop a process
> - `fg` to bring to the foreground a background processes
> - `jobs` to display background processes
> - `bg` to start a background process
> - `stress` to launch a mock computation
> - `nice`/`renince` to change the nice value of a process
[To learn how to articulate processes you can head to the next section.](./7_streams_and_pipes.html)
---
title: Unix Streams and pipes
author: "Laurent Modolo"
---
```{r include = FALSE}
if (!require("fontawesome")) {
install.packages("fontawesome")
}
library(fontawesome)
knitr::opts_chunk$set(echo = TRUE)
knitr::opts_chunk$set(comment = NA)
```
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" />
</a>
Objective: Understand function of streams and pipes in Unix systems
When you read a file you start at the top from left to right, you read a flux of information which stops at the end of the file.
Unix streams are much the same things instead of opening a file as a whole bunch of data, process can process it as a flux. There are 3 standard Unix streams:
0. **stdin** the **st**an**d**ard **in**put
1. **stdout** the **st**an**d**ard **out**put
2. **sterr** the **st**an**d**ard **err**or
Historically, **stdin** has been the card reader or the keyboard, while the two others where the card puncher or the display.
The command `cat `simply read from **stdin** and displays the results on **stdout**
```sh
cat
I can talk with
myself
```
It can also read files and display the results on **stdout**
```sh
cat .bashrc
```
## Streams manipulation
You can use the `>` character to redirect a flux toward a file. The following command makes a copy of your `.bashrc` files.
```sh
cat .bashrc > my_bashrc
```
Check the results of your command with `less`.
Following the same principle create a `my_cal` file containing the **cal**endar of this month. Check the results with the command `less`
Reuse the same command with the unnamed option `1999`. Check the results with the command `less`. What happened ?
Try the following command
```sh
cal -N 2 > my_cal
```
What is the content of `my_cal` what happened ?
The `>` command can have an argument, the syntax to redirect **stdout** to a file is `1>` it's also the default option (equivalent to `>`). Here the `-N` option doesn't exist, `cal` throws an error. Errors are sent to **stderr** which have the number 2.
Save the error message in `my_cal` and check the results with `less`.
We have seen that `>` overwrite the content of the file. Try the following commands:
```sh
cal 2020 > my_cal
cal >> my_cal
cal -N 2 2>> my_cal
```
Check the results with the command `less`.
The command `>` sends the stream from the left to the file on the right. Try the following:
```sh
cat < my_cal
```
What is the function of the command `<`?
You can use different redirection on the same process. Try the following command:
```sh
cat <<EOF > my_notes
```
Type some text and type `EOF` on a new line. `EOF` stand for **e**nd **o**f **f**ile, it's a conventional sequence to use to indicate the start and the end of a file in a stream.
What happened ? Can you check the content of `my_notes` ? How would you modify this command to add new notes?
Finally, you can redirect a stream toward another stream with the following syntax:
```sh
cal -N2 2&> my_redirection
cal 2&>> my_redirection
```
## Pipes
The last stream manipulation that we are going to see is the pipe which transforms the **stdout** of a process into the **stding** of the next. Pipes are useful to chain multiples simple operations. The pipe operator is `| `
```sh
cal 2020 | less
```
What is the difference between with this command ?
```sh
cal 2020 | cat | cat | less
```
The command `zcat` has the same function as the command `cat` but for compressed files in [`gzip` format](https://en.wikipedia.org/wiki/Gzip).
The command `wget` download files from a url to the corresponding file. Don't run the following command which would download the human genome:
```sh
wget http://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/hg38.fa.gz
```
We are going to use the `-q` switch which silence `wget` (no download progress bar or such), and the option `-O` which allows use to set the name of the output file. In Unix setting the output file to `-` allow you to write the output on the **stdout** stream.
Analyze the following command, what would it do ?
```sh
wget -q -O - http://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/hg38.fa.gz | gzip -dc | less
```
Remember that most Unix command process input and output line by line. Which means that you can process huge datasets without intermediate files or huge RAM capacity.
> We have users the following commands:
>
> - `cat`/ `zcat` to display information in **stdout**
> - `>` / `>>` / `<` / `<<` to redirect a flux
> - `|` the pipe operator to connect processes
> - `wget` to download files
[You can head to the next session to apply pipe and stream manipulation.](./8_text_manipulation.html)
---
title: Text manipulation
author: "Laurent Modolo"
---
```{r include = FALSE}
if (!require("fontawesome")) {
install.packages("fontawesome")
}
library(fontawesome)
knitr::opts_chunk$set(echo = TRUE)
knitr::opts_chunk$set(comment = NA)
```
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" />
</a>
Objective: Learn simple ways to work with text file in Unix
One of the great things with command line tools is that they are simple and fast. Which means that they are great for handling large files. And as bioinformaticians you have to handle large files, so you need to use command line tools for that.
## Text search
The file [hg38.ncbiRefSeq.gtf.gz](http://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/genes/hg38.ncbiRefSeq.gtf.gz) contains the RefSeq annotation for hg38 in [GFT format](http://www.genome.ucsc.edu/FAQ/FAQformat.html#format4)
We can download files with the `wget` command. Here the annotation is in **gz** format which is a compressed format, you can use the `gzip` tool to handle **gz** files.
On useful command to check large text file is the `head `command.
```sh
wget -q -O - http://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/genes/hg38.ncbiRefSeq.gtf.gz | gzip -dc | head
```
You can change the number of lines displayed with the option `-n number_of_line`. The command `tail` has the same function as `head` but starting from the end of the file.
Try the `tail` for the same number of lines displayed, does the computation take the same time ?
Download the `hg38.ncbiRefSeq.gtf.gz` file in your `~/`.
The program `grep string` allows you to search for *string* through a file or stream line by line.
```sh
gzip -dc hg38.ncbiRefSeq.gtf.gz | grep "chr2" | head
```
What is the last annotation on the chromosome 1 (to write a tabulation character you can type `\t`) ?
You can count things in text file with the command `wc` read the `wc` **man**ual to see how you can count lines in a file.
Does the number of *3UTR* match the number of *5UTR* ?
How many transcripts does the gene *CCR7* have ?
## Regular expression
When you do a loot text search, you will encounter regular expressions (regexp), which allow you to perform fuzzy search. To run `grep` in regexp mode you can use the switch. `-E`
The most basic form fo regexp si the exact match:
```sh
gzip -dc hg38.ncbiRefSeq.gtf.gz | head | grep -E "gene_id"
```
You can use the `.` wildcard character to match anything
```sh
gzip -dc hg38.ncbiRefSeq.gtf.gz | head | grep -E "...._id"
```
There are different special characters in regexp, but you can use `\` to escape them. For example, if you search for **.** you can use the following regexp
```sh
gzip -dc hg38.ncbiRefSeq.gtf.gz | head | grep -E "\."
```
### Character classes and alternatives
There are a number of special patterns that match more than one character. You’ve already seen `.`, which matches any character apart from a newline. There are four other useful tools:
- `\d`: matches any digit.
- `\s`: matches any whitespace (e.g. space, tab, newline).
- `\S`: matches any non-whitespace.
- `[abc]`: matches a, b, or c.
- `[^abc]`: matches anything except a, b, or c.
- `[a-z]`: Match any letter of the alphabet
Search for two digits followed by an uppercase letter and one digit.
<details><summary>Solution</summary>
<p>
```sh
gzip -dc hg38.ncbiRefSeq.gtf.gz | head | perl -E "\d\d[A-Z]\d"
```
</p>
</details>
### Anchors
By default, regular expressions will match any part of a string. It’s often useful to *anchor* the regular expression so that it matches from the start or end of the string. You can use
- `^` to match the start of the string.
- `$` to match the end of the string.
```sh
gzip -dc hg38.ncbiRefSeq.gtf.gz | head | grep -E ";"
gzip -dc hg38.ncbiRefSeq.gtf.gz | head | grep -E ";$"
```
```sh
gzip -dc hg38.ncbiRefSeq.gtf.gz | head | grep -E "c"
gzip -dc hg38.ncbiRefSeq.gtf.gz | head | grep -E "^c"
```
### Repetition
The next step up in power involves controlling how many times a pattern matches
- `?`: 0 or 1
- `+`: 1 or more
- `*`: 0 or more
What is the following regexp going to match ?
```sh
gzip -dc hg38.ncbiRefSeq.gtf.gz | head | grep -E "[a-z]*_[a-z]*\s\"[1-3]\""
```
You can also specify the number of matches precisely:
- `{n}`: exactly n
- `{n,}`: n or more
- `{,m}`: at most m
- `{n,m}`: between n and m
What is the following regexp going to match ?
```sh
gzip -dc hg38.ncbiRefSeq.gtf.gz | grep -E "^[a-z]{3}[2-3]\s.*exon\s\d{4,5}\s\d{4,5}.*"
```
How many gene names of more than 16 characters does the annotation contain ?
<details><summary>Solution</summary>
<p>
```sh
gzip -dc hg38.ncbiRefSeq.gtf.gz | grep -E "transcript\s.*gene_id\s\"\S{16,}\";" | wc -l
```
</p>
</details>
### Grouping and back references
You can group match using `()`, for example the following regexp match doublet of *12* .
```sh
gzip -dc hg38.ncbiRefSeq.gtf.gz | grep -E "(12){2}"
```
Grouping is also used for back references in the case of text replacement. You can use the command `sed` for text replacement. The syntax of `sed` for replacement is the following: `sed -E 's|regexp|\n|g` where `n` is the grouping number. `s` stand for substitute and `g` stand for global (which means that is they are different substitutions per line `sed` won't stop at the first one).
Try the following replacement regexp
```sh
gzip -dc hg38.ncbiRefSeq.gtf.gz | head | sed -E 's|(transcript_).{2}|\1number|g'
```
Try to write a `sed` command to replace *ncbiRefSeq* with *transcript_id* .
<details><summary>Solution</summary>
<p>
```sh
gzip -dc hg38.ncbiRefSeq.gtf.gz | head | sed -E 's|ncbiRefSeq(.*)(transcript_id "([A-Z_0-9.]*))|\3\1\2|g'
```
</p>
</details>
Regexp can be very complex see for example [a regex to validate an email on starckoverflow](https://stackoverflow.com/questions/201323/how-to-validate-an-email-address-using-a-regular-expression/201378#201378). When you start you can always use for a given regexp to a more experienced used (just give him the kind of text you want to match and not match). You can test your regex easily with the [regex101 website](https://regex101.com/).
## Sorting
GTF files should be sorted by chromosome, starting position and end position. But you can change that with the command `sort` to select the column to sort on you can use the option `-k n,n` where `n` is the column number.
You need to specify where sort keys start *and where they end*, otherwise (as in when you use `-k 3` instead of `-k 3,3`) they end at the end of the line.
For example, the following command `sort` on the 4th column and then on the 5th when the values of the 4th column are equal.
```sh
gzip -dc hg38.ncbiRefSeq.gtf.gz | head -n 10000 | sort -k 4,4 -k 5,5 | head
```
> Sorting operations are complex and can take a long time
You can add more option to the sorting of each column, for example `r` for reverse order `d` for dictionary order or `n` for numeric order.
What will the following command do ?
```sh
gzip -dc hg38.ncbiRefSeq.gtf.gz | head -n 10000 | sort -k 3,3d -k 4,4n | head
```
Use the `-u` option to count the number of different annotation type based on the 3rd column
<details><summary>Solution</summary>
<p>
```sh
gzip -dc hg38.ncbiRefSeq.gtf.gz | head -n 10000 | sort -k 3,3d -u | wc -l
```
</p>
</details>
You can check if a file is already sorted with the `-c` switch. Check if the gtf file is sorted by chromosome, start and end position.
<details><summary>Solution</summary>
<p>
```sh
gzip -dc hg38.ncbiRefSeq.gtf.gz | head -n 10000 | sort -k 1,1 -k 4,4n -k 5,5n -c
```
</p>
</details>
## Field extractor
Sometime rather than using complex regexp, we want to extract a particular column from a file. You can use the command `cut` to do that.
The following command extracts the 3rd column of the annotation
```sh
gzip -dc hg38.ncbiRefSeq.gtf.gz | head | cut -f 3
```
You can change the field separator with the option `-d`, set it to `";"` to extract the *transcript_id* and *gene_name* from the information column.
<details><summary>Solution</summary>
<p>
```sh
gzip -dc hg38.ncbiRefSeq.gtf.gz | head | cut -f 2 -f 5 -d ";"
```
</p>
</details>
## Concatenation
There are different tools to concatenate files from the command line `cat` for vertical concatenation and `paste` for horizontal concatenation.
```sh
cat .bashrc .bashrc | wc -l
```
What will be the results of the following command ?
```sh
gzip -dc hg38.ncbiRefSeq.gtf.gz | head | paste - -
```
## Text editor
You often have access to different text editors from the common line, two of the most popular ones are `vim` and `nano`.
`nano` is more friendly to use than `vim` but also very limited.
To open a text file you can type `editor file_path`.
In `nano` everything is written at the bottom, so you only have to remember that `^`is the symbol for the key `Ctrl`.
Open you `.bashrc` file and delete any comment line (starting with the `#` character).
`vim` is a child of the project `vi` (which should also be available on your system), and which bring him more functionality. The workings of `vim` can be a little strange at first, but you have to understand that on a US keyboard the distance that your finger have to travel while using `vim` is minimal.
You have 3 modes in `vim`:
- The **normal** mode, where you can navigate the file and enter command with the `:` key. You can come back to this mode by pressing `Esc`
- The **insert** mode, where you can write things. You enter this mode with the `i` key or any other key insertion key (for example `a` to insert after the cursor or `A` to insert at the end of the line)
- The **visual** mode where you can select text for copy/paste action. You can enter this mode with the `v` key
If you want to learn more about `vim`, you can start with the <https://vim-adventures.com/> website. Once you master `vim` everything is faster but you will have to practice a lot.
> We have used the following commands:
>
> - `head` / `tail` to display head or tail of a file
> - `wget` to download files
> - `gzip` to extract `tar.gz` files
> - `grep` to search text files
> - `wc` to count things
> - `sed` to search and replace string of text
> - `sort` to sort files on specific field
> - `cut` to extract a specific field
> - `cat` / `paste` for concatenation
> - `nano` / `vim` for text edition
In the next session, we are going to apply the logic of pipes and text manipulation to [batch processing.](./9_batch_processing.html)
---
title: Batch processing
author: "Laurent Modolo"
---
```{r include = FALSE}
if (!require("fontawesome")) {
install.packages("fontawesome")
}
library(fontawesome)
knitr::opts_chunk$set(echo = TRUE)
knitr::opts_chunk$set(comment = NA)
```
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" />
</a>
Objective: Learn basics of batch processing in GNU/Linux
In the previous section, we have seen how to handle streams and text. We can use this knowledge to generate list of command instead of text. This is called batch processing.
In everyday life, you may want to run command sequentiality without using pipes.
To run `CMD1` and then run `CMD2` you can use the `;` operator
```
CMD1 ; CMD2
```
To run `CMD1` and then run `CMD2` if `CMD1` didn’t throw an error, you can use the `&&` operator which is safer than the `;` operator.
```sh
CMD1 && CMD2
```
You can also use the `||` to manage errors and run `CMD2` if `CMD1` failed.
```sh
CMD1 || CMD2
```
## Executing list of commands
The easiest option to execute list of command is to use `xargs`. `xargs` reads arguments from **stdin** and use them as arguments for a command. In UNIX systems the command `echo` send string of character into **stdout**. We are going to use this command to learn more about `xargs`.
```sh
echo "hello world"
```
In general a string of character differs from a command when it’s placed between quotes.
The two following commands are equivalent, why ?
```sh
echo "file1 file2 file3" | xargs touch
touch file1 file2 file3
```
You can display the command executed by `xargs` with the switch `-t`.
By default the number of arguments sent by `xargs` is defined by the system. You can change it with the option `-n N`, where `N` is the number of arguments sent. Use the option `-t` and `-n` to run the previous command as 3 separate `touch` commands.
<details><summary>Solution</summary>
<p>
```sh
echo "file1 file2 file3" | xargs -t -n 1 touch
```
</p>
</details>
Sometime, the arguments are not separated by space but by other characters. You can use the `-d` option to specify them. Execute `touch`1 time from the following command:
```sh
echo "file1;file2;file3"
```
<details><summary>Solution</summary>
<p>
```sh
echo "file1;file2;file3" | xargs -t -d \; touch
```
</p>
</details>
To reuse the arguments sent to `xargs` you can use the command `-I` which defines a string corresponding to the argument. Try the following command, what does the **man**ual says about the `-c` option of the command `cut` ?
```sh
ls -l file* | cut -c 44- | xargs -t -I % ln -s % link_%
```
Instead of using `ls` the command `xargs` is often used with the command `find`. The command `find` is a powerful command to search for files.
Modify the following command to make a non-hidden copy of all the file with a name starting with *.bash* in your home folder
```sh
find . -name ".bash*" | sed 's|./.||g'
```
<details><summary>Solution</summary>
<p>
```sh
find . -name ".bash*" | sed 's|./.||g' | xargs -t -I % cp .% %
```
</p>
</details>
You can try to remove all the files in the `/tmp` folder with the following command:
```sh
find /tmp/ -type f | xargs -t rm
```
Modify this command to remove every folder in the `/tmp` folder.
<details><summary>Solution</summary>
<p>
```sh
find /tmp/ -type d | xargs -t rm -R
```
</p>
</details>
## Writing `awk` commands
`xargs` It is a simple solution for writing batch commands, but if you want to write more complex command you are going to need to learn `awk`. `awk` is a programming language by itself, but you don’t need to know everything about `awk` to use it.
You can to think of `awk` as a `xargs -I $N` command where `$1` correspond to the first column `$2` to the second column, etc.
There are also some predefined variables that you can use like.
- `$0` Correspond to all the columns.
- `FS` the field separator used
- `NF` the number of fields separated by `FS`
- `NR` the number of records already read
A `awk` program is a chain of commands with the form `motif { action }`
- the `motif` define where there `action` is executed
- there `action` is what you want to do
They `motif` can be
- a regexp
- The keyword `BEGIN`or `END` (before reading the first line, and after reading the last line)
- a comparison like `<`, `<=`, `==`, `>=`, `>` or `!=`
- a combination of the three separated by `&&` (AND), `||`(OR) and `!` (Negation)
- a range of line `motif_1,motif_2`
With `awk` you can
Count the number of lines in a file
```sh
awk '{ print NR " : " $0 }' file
```
Modify this command to only display the total number of line with awk (like `wc -l`)
<details><summary>Solution</summary>
<p>
```sh
awk 'END{ print NR }' file
```
</p>
</details>
Convert a tabulated sequences file into fasta format
```sh
awk -vOFS='' '{print ">",$1,"\n",$2,"\n";}' two_column_sample_tab.txt > sample1.fa
```
Modify this command to only get a list of sequence names in a fasta file
<details><summary>Solution</summary>
<p>
```sh
awk -vOFS='' '{print $1 "\n";}' two_column_sample_tab.txt > seq_name.txt
```
</p>
</details>
Convert a multiline fasta file into a single line fasta file
```sh
awk '!/^>/ { printf "%s", $0; n = "\n" } /^>/ { print n $0; n = "" } END { printf "%s", n }' sample.fa > sample1_singleline.fa
```
Convert fasta sequences to uppercase
```sh
awk '/^>/ {print($0)}; /^[^>]/ {print(toupper($0))}' file.fasta > file_upper.fasta
```
Modify this command to only get a list of sequence names in a fasta file un lowercase
<details><summary>Solution</summary>
<p>
```sh
awk '/[^>]/ {print(tolower($0))}' file.fasta > seq_name_lower.txt
```
</p>
</details>
Return a list of sequence_id sequence_length from a fasta file
```sh
awk 'BEGIN {OFS = "\n"}; /^>/ {print(substr(sequence_id, 2)" "sequence_length); sequence_length = 0; sequence_id = $0}; /^[^>]/ {sequence_length += length($0)}; END {print(substr(sequence_id, 2)" "sequence_length)}' file.fasta
```
Count the number of bases in a fastq.gz file
```sh
(gzip -dc $0) | awk 'NR%4 == 2 {basenumber += length($0)} END {print basenumber}'
```
Only read with more than 20bp from a fastq
```sh
awk 'BEGIN {OFS = "\n"} {header = $0 ; getline seq ; getline qheader ; getline qseq ; if (length(seq) >= 20){print header, seq, qheader, qseq}}' < input.fastq > output.fastq
```
## Writing a bash script
When you start writing complicated command, you may want to save them to reuse them later.
You can find everything that you are typing in your `bash`in the `~/.bash_history` file, but working with this file can be tedious as it also contains all the command that you mistype. A good solution, for reproducibility is to write `bash` scripts. A bash script is simply a text file that contains a sequence of `bash`commands.
As you use `bash` in your terminal, you can execute a `bash` script with the following command:
```bash
source myscrip.sh
```
It’s usual to write the `.sh` extension for `shell`scripts.
Write a bash script named `download_hg38.sh` that download the [hg38.ncbiRefSeq.gtf.gz](http://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/genes/hg38.ncbiRefSeq.gtf.gz) file, then extract it and that says that it has done it.
The `\` character like in regexp cancel the meaning of what follow, you can use it to split your one-liner scripts over many lines to use the `&&` operator.
<details><summary>Solution</summary>
<p>
```sh
wget http://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/genes/hg38.ncbiRefSeq.gtf.gz && \
gzip -dc hg38.ncbiRefSeq.gtf.gz && \
echo "download and extraction complete"
```
</p>
</details>
### shebang
In your first bash script, the only thing saying that your script is a bash script is its extension. But most of the time UNIX system doesn’t care about file extension, a text file is a text file.
To tell the system that your text file is a bash script you need to add a **shebang**. A **shebang** is a special first line that starts with a `#!` followed by the path of the interpreter for your script.
For example, for a bash script in a system where `bash` is installed in `/bin/bash` the **shebang** is:
```bash
##!/bin/bash
```
When you are not sure `which`is the path of the tools available to interpret your script, you can use the following shebang:
```bash
##!/usr/bin/env bash
```
You can add a **shebang** to your script and add it the e**x**ecutable right.
<details><summary>Solution</summary>
<p>
```sh
chmod u+x download_hg38.sh
```
</p>
</details>
Now you can execute your script with the command:
```bash
./download_hg38.sh
```
Congratulations you wrote your first program !
### PATH
Where did they `/usr/bin/env` find the information about your bash ? Why did we have to write a `./` before our script if we are in the same folder ?
This is all linked to the **PATH** bash variable. Like in many programming languages `bash` have what we call *variables*. *variables* are named storage for temporary information. You can print a list of all your environment variables (variables loaded in your `bash` memory), with the command `printenv`.
To create a new variable you can use the following syntax:
```sh
VAR_NAME="text"
VAR_NAME2=2
```
Create a `IDENTIY` variable with your first and last names.
<details><summary>Solution</summary>
<p>
```sh
IDENTITY="First name Last Name"
```
</p>
</details>
It’s good practice to write your `bash` variable in uppercase with `_` in place of spaces.
You can access the value of an existing `bash` variable with the `$VAR_NAME`
To display the value of your `IDENTITY` variable with `echo` you can write:
```sh
echo $IDENTITY
```
When you want to mix variable value and text you can use the two following syntax:
```sh
echo "my name is "$IDENTITY
echo "my name is ${IDENTITY}"
```
Going back to the `printenv` You can see a **PWD** variable that store your current path, a **SHELL** variable that store your current shell, and you can see a **PATH** variable that stores a loot of file path separated by `:`.
The **PATH** variable contains every folder where to look for executable programs. Executable programs can be binary files or text files with a **shebang**.
Display the content of `PATH` with `echo`
<details><summary>Solution</summary>
<p>
```sh
echo $PATH
```
</p>
</details>
You can create a `scripts`folder and move your `download_hg38.sh` script in it. Then we can modify the `PATH` variable to include the `scripts` folder in it.
> Don’t erase your `PATH` variable !
<details><summary>Solution</summary>
<p>
```sh
mkdir ~/scripts
mv `download_hg38.sh` ~/scripts/
PATH=$PATH:~/scripts/
```
</p>
</details>
You can check the result of your command with `echo $PATH`
Try to call your `download_hg38.sh` from anywhere on the file tree. Congratulation you installed your first UNIX program !
### Arguments
You can pass argument to your bash scripts, writing the following command:
```sh
my_script.sh arg1 arg2 arg3
```
Means that from within the script:
- `$0` will give you the name of the script (`my_script.sh`)
- `$1`, `$2`, `$3`, `$n` will give you the value of the arguments (`arg1`, `arg2`, `arg3`, `argn`)
- `$$` the process id of the current shell
- `$#` the total number of arguments passed to the script
- `$@`the value of all the arguments passed to the script
- `$?` the exit status of the last executed command
- `$!`the process id of the last executed command
You can write the following `variables.sh` script in your `scripts` folder:
```sh
##!/bin/bash
echo "Name of the script: $0"
echo "Total number of arguments: $#"
echo "Values of all the arguments: $@"
```
And you can try to call it with some arguments !
> We have used the following commands:
>
> - `echo` to display text
> - `xarg` to execute a chain of commands
> - `awk` to execute complex chain of commands
> - `;` `&&` and `||` to chain commands
> - `source` to load a script
> - `shebang` to specify the language of a script
> - `PATH` to install script
In the next session, we are going to learn how to execute command on other computers with [ssh.](./10_network_and_ssh.html)
CeCILL FREE SOFTWARE LICENSE AGREEMENT
Version 2.1 dated 2013-06-21
Notice
This Agreement is a Free Software license agreement that is the result
of discussions between its authors in order to ensure compliance with
the two main principles guiding its drafting:
* firstly, compliance with the principles governing the distribution
of Free Software: access to source code, broad rights granted to users,
* secondly, the election of a governing law, French law, with which it
is conformant, both as regards the law of torts and intellectual
property law, and the protection that it offers to both authors and
holders of the economic rights over software.
The authors of the CeCILL (for Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre])
license are:
Commissariat à l'énergie atomique et aux énergies alternatives - CEA, a
public scientific, technical and industrial research establishment,
having its principal place of business at 25 rue Leblanc, immeuble Le
Ponant D, 75015 Paris, France.
Centre National de la Recherche Scientifique - CNRS, a public scientific
and technological establishment, having its principal place of business
at 3 rue Michel-Ange, 75794 Paris cedex 16, France.
Institut National de Recherche en Informatique et en Automatique -
Inria, a public scientific and technological establishment, having its
principal place of business at Domaine de Voluceau, Rocquencourt, BP
105, 78153 Le Chesnay cedex, France.
Preamble
The purpose of this Free Software license agreement is to grant users
the right to modify and redistribute the software governed by this
license within the framework of an open source distribution model.
The exercising of this right is conditional upon certain obligations for
users so as to preserve this status for all subsequent redistributions.
In consideration of access to the source code and the rights to copy,
modify and redistribute granted by the license, users are provided only
with a limited warranty and the software's author, the holder of the
economic rights, and the successive licensors only have limited liability.
In this respect, the risks associated with loading, using, modifying
and/or developing or reproducing the software by the user are brought to
the user's attention, given its Free Software status, which may make it
complicated to use, with the result that its use is reserved for
developers and experienced professionals having in-depth computer
knowledge. Users are therefore encouraged to load and test the
suitability of the software as regards their requirements in conditions
enabling the security of their systems and/or data to be ensured and,
more generally, to use and operate it in the same conditions of
security. This Agreement may be freely reproduced and published,
provided it is not altered, and that no provisions are either added or
removed herefrom.
This Agreement may apply to any or all software for which the holder of
the economic rights decides to submit the use thereof to its provisions.
Frequently asked questions can be found on the official website of the
CeCILL licenses family (http://www.cecill.info/index.en.html) for any
necessary clarification.
Article 1 - DEFINITIONS
For the purpose of this Agreement, when the following expressions
commence with a capital letter, they shall have the following meaning:
Agreement: means this license agreement, and its possible subsequent
versions and annexes.
Software: means the software in its Object Code and/or Source Code form
and, where applicable, its documentation, "as is" when the Licensee
accepts the Agreement.
Initial Software: means the Software in its Source Code and possibly its
Object Code form and, where applicable, its documentation, "as is" when
it is first distributed under the terms and conditions of the Agreement.
Modified Software: means the Software modified by at least one
Contribution.
Source Code: means all the Software's instructions and program lines to
which access is required so as to modify the Software.
Object Code: means the binary files originating from the compilation of
the Source Code.
Holder: means the holder(s) of the economic rights over the Initial
Software.
Licensee: means the Software user(s) having accepted the Agreement.
Contributor: means a Licensee having made at least one Contribution.
Licensor: means the Holder, or any other individual or legal entity, who
distributes the Software under the Agreement.
Contribution: means any or all modifications, corrections, translations,
adaptations and/or new functions integrated into the Software by any or
all Contributors, as well as any or all Internal Modules.
Module: means a set of sources files including their documentation that
enables supplementary functions or services in addition to those offered
by the Software.
External Module: means any or all Modules, not derived from the
Software, so that this Module and the Software run in separate address
spaces, with one calling the other when they are run.
Internal Module: means any or all Module, connected to the Software so
that they both execute in the same address space.
GNU GPL: means the GNU General Public License version 2 or any
subsequent version, as published by the Free Software Foundation Inc.
GNU Affero GPL: means the GNU Affero General Public License version 3 or
any subsequent version, as published by the Free Software Foundation Inc.
EUPL: means the European Union Public License version 1.1 or any
subsequent version, as published by the European Commission.
Parties: mean both the Licensee and the Licensor.
These expressions may be used both in singular and plural form.
Article 2 - PURPOSE
The purpose of the Agreement is the grant by the Licensor to the
Licensee of a non-exclusive, transferable and worldwide license for the
Software as set forth in Article 5 <#scope> hereinafter for the whole
term of the protection granted by the rights over said Software.
Article 3 - ACCEPTANCE
3.1 The Licensee shall be deemed as having accepted the terms and
conditions of this Agreement upon the occurrence of the first of the
following events:
* (i) loading the Software by any or all means, notably, by
downloading from a remote server, or by loading from a physical medium;
* (ii) the first time the Licensee exercises any of the rights granted
hereunder.
3.2 One copy of the Agreement, containing a notice relating to the
characteristics of the Software, to the limited warranty, and to the
fact that its use is restricted to experienced users has been provided
to the Licensee prior to its acceptance as set forth in Article 3.1
<#accepting> hereinabove, and the Licensee hereby acknowledges that it
has read and understood it.
Article 4 - EFFECTIVE DATE AND TERM
4.1 EFFECTIVE DATE
The Agreement shall become effective on the date when it is accepted by
the Licensee as set forth in Article 3.1 <#accepting>.
4.2 TERM
The Agreement shall remain in force for the entire legal term of
protection of the economic rights over the Software.
Article 5 - SCOPE OF RIGHTS GRANTED
The Licensor hereby grants to the Licensee, who accepts, the following
rights over the Software for any or all use, and for the term of the
Agreement, on the basis of the terms and conditions set forth hereinafter.
Besides, if the Licensor owns or comes to own one or more patents
protecting all or part of the functions of the Software or of its
components, the Licensor undertakes not to enforce the rights granted by
these patents against successive Licensees using, exploiting or
modifying the Software. If these patents are transferred, the Licensor
undertakes to have the transferees subscribe to the obligations set
forth in this paragraph.
5.1 RIGHT OF USE
The Licensee is authorized to use the Software, without any limitation
as to its fields of application, with it being hereinafter specified
that this comprises:
1. permanent or temporary reproduction of all or part of the Software
by any or all means and in any or all form.
2. loading, displaying, running, or storing the Software on any or all
medium.
3. entitlement to observe, study or test its operation so as to
determine the ideas and principles behind any or all constituent
elements of said Software. This shall apply when the Licensee
carries out any or all loading, displaying, running, transmission or
storage operation as regards the Software, that it is entitled to
carry out hereunder.
5.2 ENTITLEMENT TO MAKE CONTRIBUTIONS
The right to make Contributions includes the right to translate, adapt,
arrange, or make any or all modifications to the Software, and the right
to reproduce the resulting software.
The Licensee is authorized to make any or all Contributions to the
Software provided that it includes an explicit notice that it is the
author of said Contribution and indicates the date of the creation thereof.
5.3 RIGHT OF DISTRIBUTION
In particular, the right of distribution includes the right to publish,
transmit and communicate the Software to the general public on any or
all medium, and by any or all means, and the right to market, either in
consideration of a fee, or free of charge, one or more copies of the
Software by any means.
The Licensee is further authorized to distribute copies of the modified
or unmodified Software to third parties according to the terms and
conditions set forth hereinafter.
5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION
The Licensee is authorized to distribute true copies of the Software in
Source Code or Object Code form, provided that said distribution
complies with all the provisions of the Agreement and is accompanied by:
1. a copy of the Agreement,
2. a notice relating to the limitation of both the Licensor's warranty
and liability as set forth in Articles 8 and 9,
and that, in the event that only the Object Code of the Software is
redistributed, the Licensee allows effective access to the full Source
Code of the Software for a period of at least three years from the
distribution of the Software, it being understood that the additional
acquisition cost of the Source Code shall not exceed the cost of the
data transfer.
5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE
When the Licensee makes a Contribution to the Software, the terms and
conditions for the distribution of the resulting Modified Software
become subject to all the provisions of this Agreement.
The Licensee is authorized to distribute the Modified Software, in
source code or object code form, provided that said distribution
complies with all the provisions of the Agreement and is accompanied by:
1. a copy of the Agreement,
2. a notice relating to the limitation of both the Licensor's warranty
and liability as set forth in Articles 8 and 9,
and, in the event that only the object code of the Modified Software is
redistributed,
3. a note stating the conditions of effective access to the full source
code of the Modified Software for a period of at least three years
from the distribution of the Modified Software, it being understood
that the additional acquisition cost of the source code shall not
exceed the cost of the data transfer.
5.3.3 DISTRIBUTION OF EXTERNAL MODULES
When the Licensee has developed an External Module, the terms and
conditions of this Agreement do not apply to said External Module, that
may be distributed under a separate license agreement.
5.3.4 COMPATIBILITY WITH OTHER LICENSES
The Licensee can include a code that is subject to the provisions of one
of the versions of the GNU GPL, GNU Affero GPL and/or EUPL in the
Modified or unmodified Software, and distribute that entire code under
the terms of the same version of the GNU GPL, GNU Affero GPL and/or EUPL.
The Licensee can include the Modified or unmodified Software in a code
that is subject to the provisions of one of the versions of the GNU GPL,
GNU Affero GPL and/or EUPL and distribute that entire code under the
terms of the same version of the GNU GPL, GNU Affero GPL and/or EUPL.
Article 6 - INTELLECTUAL PROPERTY
6.1 OVER THE INITIAL SOFTWARE
The Holder owns the economic rights over the Initial Software. Any or
all use of the Initial Software is subject to compliance with the terms
and conditions under which the Holder has elected to distribute its work
and no one shall be entitled to modify the terms and conditions for the
distribution of said Initial Software.
The Holder undertakes that the Initial Software will remain ruled at
least by this Agreement, for the duration set forth in Article 4.2 <#term>.
6.2 OVER THE CONTRIBUTIONS
The Licensee who develops a Contribution is the owner of the
intellectual property rights over this Contribution as defined by
applicable law.
6.3 OVER THE EXTERNAL MODULES
The Licensee who develops an External Module is the owner of the
intellectual property rights over this External Module as defined by
applicable law and is free to choose the type of agreement that shall
govern its distribution.
6.4 JOINT PROVISIONS
The Licensee expressly undertakes:
1. not to remove, or modify, in any manner, the intellectual property
notices attached to the Software;
2. to reproduce said notices, in an identical manner, in the copies of
the Software modified or not.
The Licensee undertakes not to directly or indirectly infringe the
intellectual property rights on the Software of the Holder and/or
Contributors, and to take, where applicable, vis-à-vis its staff, any
and all measures required to ensure respect of said intellectual
property rights of the Holder and/or Contributors.
Article 7 - RELATED SERVICES
7.1 Under no circumstances shall the Agreement oblige the Licensor to
provide technical assistance or maintenance services for the Software.
However, the Licensor is entitled to offer this type of services. The
terms and conditions of such technical assistance, and/or such
maintenance, shall be set forth in a separate instrument. Only the
Licensor offering said maintenance and/or technical assistance services
shall incur liability therefor.
7.2 Similarly, any Licensor is entitled to offer to its licensees, under
its sole responsibility, a warranty, that shall only be binding upon
itself, for the redistribution of the Software and/or the Modified
Software, under terms and conditions that it is free to decide. Said
warranty, and the financial terms and conditions of its application,
shall be subject of a separate instrument executed between the Licensor
and the Licensee.
Article 8 - LIABILITY
8.1 Subject to the provisions of Article 8.2, the Licensee shall be
entitled to claim compensation for any direct loss it may have suffered
from the Software as a result of a fault on the part of the relevant
Licensor, subject to providing evidence thereof.
8.2 The Licensor's liability is limited to the commitments made under
this Agreement and shall not be incurred as a result of in particular:
(i) loss due the Licensee's total or partial failure to fulfill its
obligations, (ii) direct or consequential loss that is suffered by the
Licensee due to the use or performance of the Software, and (iii) more
generally, any consequential loss. In particular the Parties expressly
agree that any or all pecuniary or business loss (i.e. loss of data,
loss of profits, operating loss, loss of customers or orders,
opportunity cost, any disturbance to business activities) or any or all
legal proceedings instituted against the Licensee by a third party,
shall constitute consequential loss and shall not provide entitlement to
any or all compensation from the Licensor.
Article 9 - WARRANTY
9.1 The Licensee acknowledges that the scientific and technical
state-of-the-art when the Software was distributed did not enable all
possible uses to be tested and verified, nor for the presence of
possible defects to be detected. In this respect, the Licensee's
attention has been drawn to the risks associated with loading, using,
modifying and/or developing and reproducing the Software which are
reserved for experienced users.
The Licensee shall be responsible for verifying, by any or all means,
the suitability of the product for its requirements, its good working
order, and for ensuring that it shall not cause damage to either persons
or properties.
9.2 The Licensor hereby represents, in good faith, that it is entitled
to grant all the rights over the Software (including in particular the
rights set forth in Article 5 <#scope>).
9.3 The Licensee acknowledges that the Software is supplied "as is" by
the Licensor without any other express or tacit warranty, other than
that provided for in Article 9.2 <#good-faith> and, in particular,
without any warranty as to its commercial value, its secured, safe,
innovative or relevant nature.
Specifically, the Licensor does not warrant that the Software is free
from any error, that it will operate without interruption, that it will
be compatible with the Licensee's own equipment and software
configuration, nor that it will meet the Licensee's requirements.
9.4 The Licensor does not either expressly or tacitly warrant that the
Software does not infringe any third party intellectual property right
relating to a patent, software or any other property right. Therefore,
the Licensor disclaims any and all liability towards the Licensee
arising out of any or all proceedings for infringement that may be
instituted in respect of the use, modification and redistribution of the
Software. Nevertheless, should such proceedings be instituted against
the Licensee, the Licensor shall provide it with technical and legal
expertise for its defense. Such technical and legal expertise shall be
decided on a case-by-case basis between the relevant Licensor and the
Licensee pursuant to a memorandum of understanding. The Licensor
disclaims any and all liability as regards the Licensee's use of the
name of the Software. No warranty is given as regards the existence of
prior rights over the name of the Software or as regards the existence
of a trademark.
Article 10 - TERMINATION
10.1 In the event of a breach by the Licensee of its obligations
hereunder, the Licensor may automatically terminate this Agreement
thirty (30) days after notice has been sent to the Licensee and has
remained ineffective.
10.2 A Licensee whose Agreement is terminated shall no longer be
authorized to use, modify or distribute the Software. However, any
licenses that it may have granted prior to termination of the Agreement
shall remain valid subject to their having been granted in compliance
with the terms and conditions hereof.
Article 11 - MISCELLANEOUS
11.1 EXCUSABLE EVENTS
Neither Party shall be liable for any or all delay, or failure to
perform the Agreement, that may be attributable to an event of force
majeure, an act of God or an outside cause, such as defective
functioning or interruptions of the electricity or telecommunications
networks, network paralysis following a virus attack, intervention by
government authorities, natural disasters, water damage, earthquakes,
fire, explosions, strikes and labor unrest, war, etc.
11.2 Any failure by either Party, on one or more occasions, to invoke
one or more of the provisions hereof, shall under no circumstances be
interpreted as being a waiver by the interested Party of its right to
invoke said provision(s) subsequently.
11.3 The Agreement cancels and replaces any or all previous agreements,
whether written or oral, between the Parties and having the same
purpose, and constitutes the entirety of the agreement between said
Parties concerning said purpose. No supplement or modification to the
terms and conditions hereof shall be effective as between the Parties
unless it is made in writing and signed by their duly authorized
representatives.
11.4 In the event that one or more of the provisions hereof were to
conflict with a current or future applicable act or legislative text,
said act or legislative text shall prevail, and the Parties shall make
the necessary amendments so as to comply with said act or legislative
text. All other provisions shall remain effective. Similarly, invalidity
of a provision of the Agreement, for any reason whatsoever, shall not
cause the Agreement as a whole to be invalid.
11.5 LANGUAGE
The Agreement is drafted in both French and English and both versions
are deemed authentic.
Article 12 - NEW VERSIONS OF THE AGREEMENT
12.1 Any person is authorized to duplicate and distribute copies of this
Agreement.
12.2 So as to ensure coherence, the wording of this Agreement is
protected and may only be modified by the authors of the License, who
reserve the right to periodically publish updates or new versions of the
Agreement, each with a separate number. These subsequent versions may
address new issues encountered by Free Software.
12.3 Any Software distributed under a given version of the Agreement may
only be subsequently distributed under the same version of the Agreement
or a subsequent version, subject to the provisions of Article 5.3.4
<#compatibility>.
Article 13 - GOVERNING LAW AND JURISDICTION
13.1 The Agreement is governed by French law. The Parties agree to
endeavor to seek an amicable solution to any disagreements or disputes
that may arise during the performance of the Agreement.
13.2 Failing an amicable solution within two (2) months as from their
occurrence, and unless emergency proceedings are necessary, the
disagreements or disputes shall be referred to the Paris Courts having
jurisdiction, by the more diligent Party.
all: index.html 1_understanding_a_computer.html 2_using_the_ifb_cloud.html 3_first_steps_in_a_terminal.html
all: public/index.html \
public/github-pandoc.css \
public/1_understanding_a_computer.html \
public/2_using_the_ifb_cloud.html \
public/3_first_steps_in_a_terminal.html \
public/4_unix_file_system.html \
public/5_users_and_rights.html \
public/6_unix_processes.html \
public/7_streams_and_pipes.html \
public/8_text_manipulation.html \
public/9_batch_processing.html \
public/10_network_and_ssh.html \
public/11_install_system_programs.html \
public/12_virtualization.html
index.html: index.md github-pandoc.css
pandoc -s -c github-pandoc.css index.md -o index.html
public/github-pandoc.css: github-pandoc.css
cp github-pandoc.css public/github-pandoc.css
cp -R img public/
cp *.Rmd public/
cp -R www public/
1_understanding_a_computer.html: 1_understanding_a_computer.md github-pandoc.css
pandoc -s --toc -c github-pandoc.css 1_understanding_a_computer.md -o 1_understanding_a_computer.html
public/index.html: index.md github-pandoc.css
pandoc -s -c github-pandoc.css index.md -o public/index.html
2_using_the_ifb_cloud.html: 2_using_the_ifb_cloud.md github-pandoc.css
pandoc -s --toc -c github-pandoc.css 2_using_the_ifb_cloud.md -o 2_using_the_ifb_cloud.html
public/1_understanding_a_computer.html: 1_understanding_a_computer.Rmd public/github-pandoc.css
cd public && Rscript -e 'rmarkdown::render("1_understanding_a_computer.Rmd")'
3_first_steps_in_a_terminal.html: 3_first_steps_in_a_terminal.md github-pandoc.css
pandoc -s --toc -c github-pandoc.css 3_first_steps_in_a_terminal.md -o 3_first_steps_in_a_terminal.html
public/2_using_the_ifb_cloud.html: 2_using_the_ifb_cloud.Rmd public/github-pandoc.css
cd public && Rscript -e 'rmarkdown::render("2_using_the_ifb_cloud.Rmd")'
public/3_first_steps_in_a_terminal.html: 3_first_steps_in_a_terminal.Rmd public/github-pandoc.css
cd public && Rscript -e 'rmarkdown::render("3_first_steps_in_a_terminal.Rmd")'
public/4_unix_file_system.html: 4_unix_file_system.Rmd public/github-pandoc.css
cd public && Rscript -e 'rmarkdown::render("4_unix_file_system.Rmd")'
public/5_users_and_rights.html: 5_users_and_rights.Rmd public/github-pandoc.css
cd public && Rscript -e 'rmarkdown::render("5_users_and_rights.Rmd")'
public/6_unix_processes.html: 6_unix_processes.Rmd public/github-pandoc.css
cd public && Rscript -e 'rmarkdown::render("6_unix_processes.Rmd")'
public/7_streams_and_pipes.html: 7_streams_and_pipes.Rmd public/github-pandoc.css
cd public && Rscript -e 'rmarkdown::render("7_streams_and_pipes.Rmd")'
public/8_text_manipulation.html: 8_text_manipulation.Rmd public/github-pandoc.css
cd public && Rscript -e 'rmarkdown::render("8_text_manipulation.Rmd")'
public/9_batch_processing.html: 9_batch_processing.Rmd public/github-pandoc.css
cd public && Rscript -e 'rmarkdown::render("9_batch_processing.Rmd")'
public/10_network_and_ssh.html: 10_network_and_ssh.Rmd public/github-pandoc.css
cd public && Rscript -e 'rmarkdown::render("10_network_and_ssh.Rmd")'
public/11_install_system_programs.html: 11_install_system_programs.Rmd public/github-pandoc.css
cd public && Rscript -e 'rmarkdown::render("11_install_system_programs.Rmd")'
public/12_virtualization.html: 12_virtualization.Rmd public/github-pandoc.css
cd public && Rscript -e 'rmarkdown::render("12_virtualization.Rmd")'
......@@ -2,15 +2,8 @@
[![cc_by_sa](./img/cc_by_sa.png)](http://creativecommons.org/licenses/by-sa/4.0/)
## Understanding a computer
All the materials are accessible at the following url:
## First steps with a terminal
## What is a process
## The network
## Files manipulation
## Processes manipulation
[https://can.gitbiopages.ens-lyon.fr/unix-command-line/](https://can.gitbiopages.ens-lyon.fr/unix-command-line/)
You can join us on the dedicated matrix channel (ask [laurent.modolo@ens-lyon.fr](mailto:laurent.modolo@ens-lyon.fr))
project:
type: book
book:
title: "UNIX command line"
author:
- "Laurent Modolo"
date: "2023-10-09"
chapters:
- index.md
- 1_understanding_a_computer.Rmd
- 2_using_the_ifb_cloud.Rmd
- 3_first_steps_in_a_terminal.Rmd
- 4_unix_file_system.Rmd
- 5_users_and_rights.Rmd
- 6_unix_processes.Rmd
- 7_streams_and_pipes.Rmd
- 8_text_manipulation.Rmd
- 9_batch_processing.Rmd
- 10_network_and_ssh.Rmd
- 11_install_system_programs.Rmd
- 12_virtualization.Rmd
body-footer: "License: Creative Commons [CC-BY-SA-4.0](http://creativecommons.org/licenses/by-sa/4.0/).<br>Made with [Quarto](https://quarto.org/)."
navbar:
search: true
right:
- icon: git
href: https://gitbio.ens-lyon.fr/can/unix-command-line
text: Sources
# bibliography: references.bib
format:
html:
theme:
light: flatly
dark: darkly
execute:
cache: true
\ No newline at end of file
/*! normalize.css v2.1.3 | MIT License | git.io/normalize */
/* ==========================================================================
HTML5 display definitions
========================================================================== */
/**
* Correct `block` display not defined in IE 8/9.
*/
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
nav,
section,
summary {
display: block;
}
/**
* Correct `inline-block` display not defined in IE 8/9.
*/
audio,
canvas,
video {
display: inline-block;
}
/**
* Prevent modern browsers from displaying `audio` without controls.
* Remove excess height in iOS 5 devices.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Address `[hidden]` styling not present in IE 8/9.
* Hide the `template` element in IE, Safari, and Firefox < 22.
*/
[hidden],
template {
display: none;
}
/* ==========================================================================
Base
========================================================================== */
/**
* 1. Set default font family to sans-serif.
* 2. Prevent iOS text size adjust after orientation change, without disabling
* user zoom.
*/
html {
font-family: sans-serif; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/**
* Remove default margin.
*/
body {
margin: 0;
}
/* ==========================================================================
Links
========================================================================== */
/**
* Remove the gray background color from active links in IE 10.
*/
a {
background: transparent;
}
/**
* Address `outline` inconsistency between Chrome and other browsers.
*/
a:focus {
outline: thin dotted;
}
/**
* Improve readability when focused and also mouse hovered in all browsers.
*/
a:active,
a:hover {
outline: 0;
}
/* ==========================================================================
Typography
========================================================================== */
/**
* Address variable `h1` font-size and margin within `section` and `article`
* contexts in Firefox 4+, Safari 5, and Chrome.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/**
* Address styling not present in IE 8/9, Safari 5, and Chrome.
*/
abbr[title] {
border-bottom: 1px dotted;
}
/**
* Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
*/
b,
strong {
font-weight: bold;
}
/**
* Address styling not present in Safari 5 and Chrome.
*/
dfn {
font-style: italic;
}
/**
* Address differences between Firefox and other browsers.
*/
hr {
-moz-box-sizing: content-box;
box-sizing: content-box;
height: 0;
}
/**
* Address styling not present in IE 8/9.
*/
mark {
background: #ff0;
color: #000;
}
/**
* Correct font family set oddly in Safari 5 and Chrome.
*/
code,
kbd,
pre,
samp {
font-family: monospace, serif;
font-size: 1em;
}
/**
* Improve readability of pre-formatted text in all browsers.
*/
pre {
white-space: pre-wrap;
}
/**
* Set consistent quote types.
*/
q {
quotes: "\201C" "\201D" "\2018" "\2019";
}
/**
* Address inconsistent and variable font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
/* ==========================================================================
Embedded content
========================================================================== */
/**
* Remove border when inside `a` element in IE 8/9.
*/
img {
border: 0;
}
/**
* Correct overflow displayed oddly in IE 9.
*/
svg:not(:root) {
overflow: hidden;
}
/* ==========================================================================
Figures
========================================================================== */
/**
* Address margin not present in IE 8/9 and Safari 5.
*/
figure {
margin: 0;
}
/* ==========================================================================
Forms
========================================================================== */
/**
* Define consistent border, margin, and padding.
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/**
* 1. Correct `color` not being inherited in IE 8/9.
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
*/
legend {
border: 0; /* 1 */
padding: 0; /* 2 */
}
/**
* 1. Correct font family not being inherited in all browsers.
* 2. Correct font size not being inherited in all browsers.
* 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.
*/
button,
input,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 2 */
margin: 0; /* 3 */
}
/**
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
* the UA stylesheet.
*/
button,
input {
line-height: normal;
}
/**
* Address inconsistent `text-transform` inheritance for `button` and `select`.
* All other form control elements do not inherit `text-transform` values.
* Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+.
* Correct `select` style inheritance in Firefox 4+ and Opera.
*/
button,
select {
text-transform: none;
}
/**
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
* and `video` controls.
* 2. Correct inability to style clickable `input` types in iOS.
* 3. Improve usability and consistency of cursor style between image-type
* `input` and others.
*/
button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
}
/**
* Re-set default cursor for disabled elements.
*/
button[disabled],
html input[disabled] {
cursor: default;
}
/**
* 1. Address box sizing set to `content-box` in IE 8/9/10.
* 2. Remove excess padding in IE 8/9/10.
*/
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
* 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
* (include `-moz` to future-proof).
*/
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; /* 2 */
box-sizing: content-box;
}
/**
* Remove inner padding and search cancel button in Safari 5 and Chrome
* on OS X.
*/
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* Remove inner padding and border in Firefox 4+.
*/
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
/**
* 1. Remove default vertical scrollbar in IE 8/9.
* 2. Improve readability and alignment in all browsers.
*/
textarea {
overflow: auto; /* 1 */
vertical-align: top; /* 2 */
}
/* ==========================================================================
Tables
========================================================================== */
/**
* Remove most spacing between table cells.
*/
table {
border-collapse: collapse;
border-spacing: 0;
}
.go-top {
position: fixed;
bottom: 2em;
right: 2em;
text-decoration: none;
background-color: #E0E0E0;
font-size: 12px;
padding: 1em;
display: inline;
}
/* Github css */
html,body{ margin: auto;
padding-right: 1em;
padding-left: 1em;
max-width: 100em; color:black;}*:not('#mkdbuttons'){margin:0;padding:0}body{font:13.34px helvetica,arial,freesans,clean,sans-serif;-webkit-font-smoothing:subpixel-antialiased;line-height:1.4;padding:3px;background:#fff;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px}p{margin:1em 0}a{color:#4183c4;text-decoration:none}body{background-color:#fff;padding:30px;margin:15px;font-size:14px;line-height:1.6}body>*:first-child{margin-top:0!important}body>*:last-child{margin-bottom:0!important}@media screen{body{box-shadow:0 0 0 1px #cacaca,0 0 0 4px #eee}}h1,h2,h3,h4,h5,h6{margin:20px 0 10px;padding:0;font-weight:bold;-webkit-font-smoothing:subpixel-antialiased;cursor:text}h1{font-size:28px;color:#000}h2{font-size:24px;border-bottom:1px solid #ccc;color:#000}h3{font-size:18px;color:#333}h4{font-size:16px;color:#333}h5{font-size:14px;color:#333}h6{color:#777;font-size:14px}p,blockquote,table,pre{margin:15px 0}ul{padding-left:30px}ol{padding-left:30px}ol li ul:first-of-type{margin-top:0}hr{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OENDRjNBN0E2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OENDRjNBN0I2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4Q0NGM0E3ODY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4Q0NGM0E3OTY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqqezsUAAAAfSURBVHjaYmRABcYwBiM2QSA4y4hNEKYDQxAEAAIMAHNGAzhkPOlYAAAAAElFTkSuQmCC) repeat-x 0 0;border:0 none;color:#ccc;height:4px;padding:0}body>h2:first-child{margin-top:0;padding-top:0}body>h1:first-child{margin-top:0;padding-top:0}body>h1:first-child+h2{margin-top:0;padding-top:0}body>h3:first-child,body>h4:first-child,body>h5:first-child,body>h6:first-child{margin-top:0;padding-top:0}a:first-child h1,a:first-child h2,a:first-child h3,a:first-child h4,a:first-child h5,a:first-child h6{margin-top:0;padding-top:0}h1+p,h2+p,h3+p,h4+p,h5+p,h6+p,ul li>:first-child,ol li>:first-child{margin-top:0}dl{padding:0}dl dt{font-size:14px;font-weight:bold;font-style:italic;padding:0;margin:15px 0 5px}dl dt:first-child{padding:0}dl dt>:first-child{margin-top:0}dl dt>:last-child{margin-bottom:0}dl dd{margin:0 0 15px;padding:0 15px}dl dd>:first-child{margin-top:0}dl dd>:last-child{margin-bottom:0}blockquote{border-left:4px solid #DDD;padding:0 15px;color:#777}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}table{border-collapse:collapse;border-spacing:0;font-size:100%;font:inherit}table th{font-weight:bold;border:1px solid #ccc;padding:6px 13px}table td{border:1px solid #ccc;padding:6px 13px}table tr{border-top:1px solid #ccc;background-color:#fff}table tr:nth-child(2n){background-color:#f8f8f8}img{max-width:100%}code,tt{margin:0 2px;padding:0 5px;white-space:nowrap;border:1px solid #eaeaea;background-color:#f8f8f8;border-radius:3px;font-family:Consolas,'Liberation Mono',Courier,monospace;font-size:12px;color:#333}pre>code{margin:0;padding:0;white-space:pre;border:0;background:transparent}.highlight pre{background-color:#f8f8f8;border:1px solid #ccc;font-size:13px;line-height:19px;overflow:auto;padding:6px 10px;border-radius:3px}pre{background-color:#f8f8f8;border:1px solid #ccc;font-size:13px;line-height:19px;overflow:auto;padding:6px 10px;border-radius:3px}pre code,pre tt{background-color:transparent;border:0}.poetry pre{font-family:Georgia,Garamond,serif!important;font-style:italic;font-size:110%!important;line-height:1.6em;display:block;margin-left:1em}.poetry pre code{font-family:Georgia,Garamond,serif!important;word-break:break-all;word-break:break-word;-webkit-hyphens:auto;-moz-hyphens:auto;hyphens:auto;white-space:pre-wrap}sup,sub,a.footnote{font-size:1.4ex;height:0;line-height:1;vertical-align:super;position:relative}sub{vertical-align:sub;top:-1px}@media print{body{background:#fff}img,pre,blockquote,table,figure{page-break-inside:avoid}body{background:#fff;border:0}code{background-color:#fff;color:#333!important;padding:0 .2em;border:1px solid #dedede}pre{background:#fff}pre code{background-color:white!important;overflow:visible}}@media screen{body.inverted{color:#eee!important;border-color:#555;box-shadow:none}.inverted body,.inverted hr .inverted p,.inverted td,.inverted li,.inverted h1,.inverted h2,.inverted h3,.inverted h4,.inverted h5,.inverted h6,.inverted th,.inverted .math,.inverted caption,.inverted dd,.inverted dt,.inverted blockquote{color:#eee!important;border-color:#555;box-shadow:none}.inverted td,.inverted th{background:#333}.inverted h2{border-color:#555}.inverted hr{border-color:#777;border-width:1px!important}::selection{background:rgba(157,193,200,0.5)}h1::selection{background-color:rgba(45,156,208,0.3)}h2::selection{background-color:rgba(90,182,224,0.3)}h3::selection,h4::selection,h5::selection,h6::selection,li::selection,ol::selection{background-color:rgba(133,201,232,0.3)}code::selection{background-color:rgba(0,0,0,0.7);color:#eee}code span::selection{background-color:rgba(0,0,0,0.7)!important;color:#eee!important}a::selection{background-color:rgba(255,230,102,0.2)}.inverted a::selection{background-color:rgba(255,230,102,0.6)}td::selection,th::selection,caption::selection{background-color:rgba(180,237,95,0.5)}.inverted{background:#0b2531;background:#252a2a}.inverted body{background:#252a2a}.inverted a{color:#acd1d5}}.highlight .c{color:#998;font-style:italic}.highlight .err{color:#a61717;background-color:#e3d2d2}.highlight .k,.highlight .o{font-weight:bold}.highlight .cm{color:#998;font-style:italic}.highlight .cp{color:#999;font-weight:bold}.highlight .c1{color:#998;font-style:italic}.highlight .cs{color:#999;font-weight:bold;font-style:italic}.highlight .gd{color:#000;background-color:#fdd}.highlight .gd .x{color:#000;background-color:#faa}.highlight .ge{font-style:italic}.highlight .gr{color:#a00}.highlight .gh{color:#999}.highlight .gi{color:#000;background-color:#dfd}.highlight .gi .x{color:#000;background-color:#afa}.highlight .go{color:#888}.highlight .gp{color:#555}.highlight .gs{font-weight:bold}.highlight .gu{color:#800080;font-weight:bold}.highlight .gt{color:#a00}.highlight .kc,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr{font-weight:bold}.highlight .kt{color:#458;font-weight:bold}.highlight .m{color:#099}.highlight .s{color:#d14}.highlight .na{color:#008080}.highlight .nb{color:#0086b3}.highlight .nc{color:#458;font-weight:bold}.highlight .no{color:#008080}.highlight .ni{color:#800080}.highlight .ne,.highlight .nf{color:#900;font-weight:bold}.highlight .nn{color:#555}.highlight .nt{color:#000080}.highlight .nv{color:#008080}.highlight .ow{font-weight:bold}.highlight .w{color:#bbb}.highlight .mf,.highlight .mh,.highlight .mi,.highlight .mo{color:#099}.highlight .sb,.highlight .sc,.highlight .sd,.highlight .s2,.highlight .se,.highlight .sh,.highlight .si,.highlight .sx{color:#d14}.highlight .sr{color:#009926}.highlight .s1{color:#d14}.highlight .ss{color:#990073}.highlight .bp{color:#999}.highlight .vc,.highlight .vg,.highlight .vi{color:#008080}.highlight .il{color:#099}.highlight .gc{color:#999;background-color:#eaf2f5}.type-csharp .highlight .k,.type-csharp .highlight .kt{color:#00F}.type-csharp .highlight .nf{color:#000;font-weight:normal}.type-csharp .highlight .nc{color:#2b91af}.type-csharp .highlight .nn{color:#000}.type-csharp .highlight .s,.type-csharp .highlight .sc{color:#a31515}
/*! normalize.css v4.1.1 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section{display:block}summary{display:list-item}audio,canvas,progress,video{display:inline-block}audio:not([controls]){display:none;height:0}progress{vertical-align:baseline}template,[hidden]{display:none !important}a{background-color:transparent}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}svg:not(:root){overflow:hidden}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}button,input,select,textarea{font:inherit;margin:0}optgroup{font-weight:bold}button,input{overflow:visible}button,select{text-transform:none}button,html [type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-cancel-button,[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-input-placeholder{color:inherit;opacity:0.54}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}*{box-sizing:border-box}input,select,textarea,button{font-family:inherit;font-size:inherit;line-height:inherit}body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:14px;line-height:1.5;color:#24292e;background-color:#fff}a{color:#0366d6;text-decoration:none}a:hover{text-decoration:underline}b,strong{font-weight:600}hr,.rule{height:0;margin:15px 0;overflow:hidden;background:transparent;border:0;border-bottom:1px solid #dfe2e5}hr::before,.rule::before{display:table;content:""}hr::after,.rule::after{display:table;clear:both;content:""}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}button{cursor:pointer;border-radius:0}[hidden][hidden]{display:none !important}details summary{cursor:pointer}details:not([open])>*:not(summary){display:none !important}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:0}h1{font-size:32px;font-weight:600}h2{font-size:24px;font-weight:600}h3{font-size:20px;font-weight:600}h4{font-size:16px;font-weight:600}h5{font-size:14px;font-weight:600}h6{font-size:12px;font-weight:600}p{margin-top:0;margin-bottom:10px}small{font-size:90%}blockquote{margin:0}ul,ol{padding-left:0;margin-top:0;margin-bottom:0}ol ol,ul ol{list-style-type:lower-roman}ul ul ol,ul ol ol,ol ul ol,ol ol ol{list-style-type:lower-alpha}dd{margin-left:0}tt,code{font-family:"SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:12px}pre{margin-top:0;margin-bottom:0;font-family:"SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:12px}.octicon{vertical-align:text-bottom}.anim-fade-in{animation-name:fade-in;animation-duration:1s;animation-timing-function:ease-in-out}.anim-fade-in.fast{animation-duration:300ms}@keyframes fade-in{0%{opacity:0}100%{opacity:1}}.anim-fade-out{animation-name:fade-out;animation-duration:1s;animation-timing-function:ease-out}.anim-fade-out.fast{animation-duration:0.3s}@keyframes fade-out{0%{opacity:1}100%{opacity:0}}.anim-fade-up{opacity:0;animation-name:fade-up;animation-duration:0.3s;animation-fill-mode:forwards;animation-timing-function:ease-out;animation-delay:1s}@keyframes fade-up{0%{opacity:0.8;transform:translateY(100%)}100%{opacity:1;transform:translateY(0)}}.anim-fade-down{animation-name:fade-down;animation-duration:0.3s;animation-fill-mode:forwards;animation-timing-function:ease-in}@keyframes fade-down{0%{opacity:1;transform:translateY(0)}100%{opacity:0.5;transform:translateY(100%)}}.anim-grow-x{width:0%;animation-name:grow-x;animation-duration:0.3s;animation-fill-mode:forwards;animation-timing-function:ease;animation-delay:0.5s}@keyframes grow-x{to{width:100%}}.anim-shrink-x{animation-name:shrink-x;animation-duration:0.3s;animation-fill-mode:forwards;animation-timing-function:ease-in-out;animation-delay:0.5s}@keyframes shrink-x{to{width:0%}}.anim-scale-in{animation-name:scale-in;animation-duration:0.15s;animation-timing-function:cubic-bezier(0.2, 0, 0.13, 1.5)}@keyframes scale-in{0%{opacity:0;transform:scale(0.5)}100%{opacity:1;transform:scale(1)}}.anim-pulse{animation-name:pulse;animation-duration:2s;animation-timing-function:linear;animation-iteration-count:infinite}@keyframes pulse{0%{opacity:0.3}10%{opacity:1}100%{opacity:0.3}}.anim-pulse-in{animation-name:pulse-in;animation-duration:0.5s}@keyframes pulse-in{0%{transform:scale3d(1, 1, 1)}50%{transform:scale3d(1.1, 1.1, 1.1)}100%{transform:scale3d(1, 1, 1)}}.hover-grow{transition:transform 0.3s;backface-visibility:hidden}.hover-grow:hover{transform:scale(1.025)}.border{border:1px #e1e4e8 solid !important}.border-y{border-top:1px #e1e4e8 solid !important;border-bottom:1px #e1e4e8 solid !important}.border-0{border:0 !important}.border-dashed{border-style:dashed !important}.border-blue{border-color:#0366d6 !important}.border-blue-light{border-color:#c8e1ff !important}.border-green{border-color:#34d058 !important}.border-green-light{border-color:#a2cbac !important}.border-red{border-color:#d73a49 !important}.border-red-light{border-color:#cea0a5 !important}.border-purple{border-color:#6f42c1 !important}.border-yellow{border-color:#d9d0a5 !important}.border-gray-light{border-color:#eaecef !important}.border-gray-dark{border-color:#d1d5da !important}.border-black-fade{border-color:rgba(27,31,35,0.15) !important}.border-top{border-top:1px #e1e4e8 solid !important}.border-right{border-right:1px #e1e4e8 solid !important}.border-bottom{border-bottom:1px #e1e4e8 solid !important}.border-left{border-left:1px #e1e4e8 solid !important}.border-top-0{border-top:0 !important}.border-right-0{border-right:0 !important}.border-bottom-0{border-bottom:0 !important}.border-left-0{border-left:0 !important}.rounded-0{border-radius:0 !important}.rounded-1{border-radius:3px !important}.rounded-2{border-radius:6px !important}.rounded-top-0{border-top-left-radius:0 !important;border-top-right-radius:0 !important}.rounded-top-1{border-top-left-radius:3px !important;border-top-right-radius:3px !important}.rounded-top-2{border-top-left-radius:6px !important;border-top-right-radius:6px !important}.rounded-right-0{border-top-right-radius:0 !important;border-bottom-right-radius:0 !important}.rounded-right-1{border-top-right-radius:3px !important;border-bottom-right-radius:3px !important}.rounded-right-2{border-top-right-radius:6px !important;border-bottom-right-radius:6px !important}.rounded-bottom-0{border-bottom-right-radius:0 !important;border-bottom-left-radius:0 !important}.rounded-bottom-1{border-bottom-right-radius:3px !important;border-bottom-left-radius:3px !important}.rounded-bottom-2{border-bottom-right-radius:6px !important;border-bottom-left-radius:6px !important}.rounded-left-0{border-bottom-left-radius:0 !important;border-top-left-radius:0 !important}.rounded-left-1{border-bottom-left-radius:3px !important;border-top-left-radius:3px !important}.rounded-left-2{border-bottom-left-radius:6px !important;border-top-left-radius:6px !important}@media (min-width: 544px){.border-sm-top{border-top:1px #e1e4e8 solid !important}.border-sm-right{border-right:1px #e1e4e8 solid !important}.border-sm-bottom{border-bottom:1px #e1e4e8 solid !important}.border-sm-left{border-left:1px #e1e4e8 solid !important}.border-sm-top-0{border-top:0 !important}.border-sm-right-0{border-right:0 !important}.border-sm-bottom-0{border-bottom:0 !important}.border-sm-left-0{border-left:0 !important}.rounded-sm-0{border-radius:0 !important}.rounded-sm-1{border-radius:3px !important}.rounded-sm-2{border-radius:6px !important}.rounded-sm-top-0{border-top-left-radius:0 !important;border-top-right-radius:0 !important}.rounded-sm-top-1{border-top-left-radius:3px !important;border-top-right-radius:3px !important}.rounded-sm-top-2{border-top-left-radius:6px !important;border-top-right-radius:6px !important}.rounded-sm-right-0{border-top-right-radius:0 !important;border-bottom-right-radius:0 !important}.rounded-sm-right-1{border-top-right-radius:3px !important;border-bottom-right-radius:3px !important}.rounded-sm-right-2{border-top-right-radius:6px !important;border-bottom-right-radius:6px !important}.rounded-sm-bottom-0{border-bottom-right-radius:0 !important;border-bottom-left-radius:0 !important}.rounded-sm-bottom-1{border-bottom-right-radius:3px !important;border-bottom-left-radius:3px !important}.rounded-sm-bottom-2{border-bottom-right-radius:6px !important;border-bottom-left-radius:6px !important}.rounded-sm-left-0{border-bottom-left-radius:0 !important;border-top-left-radius:0 !important}.rounded-sm-left-1{border-bottom-left-radius:3px !important;border-top-left-radius:3px !important}.rounded-sm-left-2{border-bottom-left-radius:6px !important;border-top-left-radius:6px !important}}@media (min-width: 768px){.border-md-top{border-top:1px #e1e4e8 solid !important}.border-md-right{border-right:1px #e1e4e8 solid !important}.border-md-bottom{border-bottom:1px #e1e4e8 solid !important}.border-md-left{border-left:1px #e1e4e8 solid !important}.border-md-top-0{border-top:0 !important}.border-md-right-0{border-right:0 !important}.border-md-bottom-0{border-bottom:0 !important}.border-md-left-0{border-left:0 !important}.rounded-md-0{border-radius:0 !important}.rounded-md-1{border-radius:3px !important}.rounded-md-2{border-radius:6px !important}.rounded-md-top-0{border-top-left-radius:0 !important;border-top-right-radius:0 !important}.rounded-md-top-1{border-top-left-radius:3px !important;border-top-right-radius:3px !important}.rounded-md-top-2{border-top-left-radius:6px !important;border-top-right-radius:6px !important}.rounded-md-right-0{border-top-right-radius:0 !important;border-bottom-right-radius:0 !important}.rounded-md-right-1{border-top-right-radius:3px !important;border-bottom-right-radius:3px !important}.rounded-md-right-2{border-top-right-radius:6px !important;border-bottom-right-radius:6px !important}.rounded-md-bottom-0{border-bottom-right-radius:0 !important;border-bottom-left-radius:0 !important}.rounded-md-bottom-1{border-bottom-right-radius:3px !important;border-bottom-left-radius:3px !important}.rounded-md-bottom-2{border-bottom-right-radius:6px !important;border-bottom-left-radius:6px !important}.rounded-md-left-0{border-bottom-left-radius:0 !important;border-top-left-radius:0 !important}.rounded-md-left-1{border-bottom-left-radius:3px !important;border-top-left-radius:3px !important}.rounded-md-left-2{border-bottom-left-radius:6px !important;border-top-left-radius:6px !important}}@media (min-width: 1012px){.border-lg-top{border-top:1px #e1e4e8 solid !important}.border-lg-right{border-right:1px #e1e4e8 solid !important}.border-lg-bottom{border-bottom:1px #e1e4e8 solid !important}.border-lg-left{border-left:1px #e1e4e8 solid !important}.border-lg-top-0{border-top:0 !important}.border-lg-right-0{border-right:0 !important}.border-lg-bottom-0{border-bottom:0 !important}.border-lg-left-0{border-left:0 !important}.rounded-lg-0{border-radius:0 !important}.rounded-lg-1{border-radius:3px !important}.rounded-lg-2{border-radius:6px !important}.rounded-lg-top-0{border-top-left-radius:0 !important;border-top-right-radius:0 !important}.rounded-lg-top-1{border-top-left-radius:3px !important;border-top-right-radius:3px !important}.rounded-lg-top-2{border-top-left-radius:6px !important;border-top-right-radius:6px !important}.rounded-lg-right-0{border-top-right-radius:0 !important;border-bottom-right-radius:0 !important}.rounded-lg-right-1{border-top-right-radius:3px !important;border-bottom-right-radius:3px !important}.rounded-lg-right-2{border-top-right-radius:6px !important;border-bottom-right-radius:6px !important}.rounded-lg-bottom-0{border-bottom-right-radius:0 !important;border-bottom-left-radius:0 !important}.rounded-lg-bottom-1{border-bottom-right-radius:3px !important;border-bottom-left-radius:3px !important}.rounded-lg-bottom-2{border-bottom-right-radius:6px !important;border-bottom-left-radius:6px !important}.rounded-lg-left-0{border-bottom-left-radius:0 !important;border-top-left-radius:0 !important}.rounded-lg-left-1{border-bottom-left-radius:3px !important;border-top-left-radius:3px !important}.rounded-lg-left-2{border-bottom-left-radius:6px !important;border-top-left-radius:6px !important}}@media (min-width: 1280px){.border-xl-top{border-top:1px #e1e4e8 solid !important}.border-xl-right{border-right:1px #e1e4e8 solid !important}.border-xl-bottom{border-bottom:1px #e1e4e8 solid !important}.border-xl-left{border-left:1px #e1e4e8 solid !important}.border-xl-top-0{border-top:0 !important}.border-xl-right-0{border-right:0 !important}.border-xl-bottom-0{border-bottom:0 !important}.border-xl-left-0{border-left:0 !important}.rounded-xl-0{border-radius:0 !important}.rounded-xl-1{border-radius:3px !important}.rounded-xl-2{border-radius:6px !important}.rounded-xl-top-0{border-top-left-radius:0 !important;border-top-right-radius:0 !important}.rounded-xl-top-1{border-top-left-radius:3px !important;border-top-right-radius:3px !important}.rounded-xl-top-2{border-top-left-radius:6px !important;border-top-right-radius:6px !important}.rounded-xl-right-0{border-top-right-radius:0 !important;border-bottom-right-radius:0 !important}.rounded-xl-right-1{border-top-right-radius:3px !important;border-bottom-right-radius:3px !important}.rounded-xl-right-2{border-top-right-radius:6px !important;border-bottom-right-radius:6px !important}.rounded-xl-bottom-0{border-bottom-right-radius:0 !important;border-bottom-left-radius:0 !important}.rounded-xl-bottom-1{border-bottom-right-radius:3px !important;border-bottom-left-radius:3px !important}.rounded-xl-bottom-2{border-bottom-right-radius:6px !important;border-bottom-left-radius:6px !important}.rounded-xl-left-0{border-bottom-left-radius:0 !important;border-top-left-radius:0 !important}.rounded-xl-left-1{border-bottom-left-radius:3px !important;border-top-left-radius:3px !important}.rounded-xl-left-2{border-bottom-left-radius:6px !important;border-top-left-radius:6px !important}}.circle{border-radius:50% !important}.box-shadow{box-shadow:0 1px 1px rgba(27,31,35,0.1) !important}.box-shadow-medium{box-shadow:0 1px 5px rgba(27,31,35,0.15) !important}.box-shadow-large{box-shadow:0 1px 15px rgba(27,31,35,0.15) !important}.box-shadow-extra-large{box-shadow:0 10px 50px rgba(27,31,35,0.07) !important}.box-shadow-none{box-shadow:none !important}.bg-white{background-color:#fff !important}.bg-blue{background-color:#0366d6 !important}.bg-blue-light{background-color:#f1f8ff !important}.bg-gray-dark{background-color:#24292e !important}.bg-gray{background-color:#f6f8fa !important}.bg-gray-light{background-color:#fafbfc !important}.bg-green{background-color:#28a745 !important}.bg-green-light{background-color:#dcffe4 !important}.bg-red{background-color:#d73a49 !important}.bg-red-light{background-color:#ffdce0 !important}.bg-yellow{background-color:#ffd33d !important}.bg-yellow-light{background-color:#fff5b1 !important}.bg-purple{background-color:#6f42c1 !important}.bg-purple-light{background-color:#f5f0ff !important}.bg-shade-gradient{background-image:linear-gradient(180deg, rgba(27,31,35,0.065), rgba(27,31,35,0)) !important;background-repeat:no-repeat !important;background-size:100% 200px !important}.text-blue{color:#0366d6 !important}.text-red{color:#cb2431 !important}.text-gray-light{color:#6a737d !important}.text-gray{color:#586069 !important}.text-gray-dark{color:#24292e !important}.text-green{color:#28a745 !important}.text-orange{color:#a04100 !important}.text-orange-light{color:#e36209 !important}.text-purple{color:#6f42c1 !important}.text-white{color:#fff !important}.text-inherit{color:inherit !important}.text-pending{color:#b08800 !important}.bg-pending{color:#dbab09 !important}.link-gray{color:#586069 !important}.link-gray:hover{color:#0366d6 !important}.link-gray-dark{color:#24292e !important}.link-gray-dark:hover{color:#0366d6 !important}.link-hover-blue:hover{color:#0366d6 !important}.muted-link{color:#586069 !important}.muted-link:hover{color:#0366d6 !important;text-decoration:none}.details-overlay[open]>summary::before{position:fixed;top:0;right:0;bottom:0;left:0;z-index:80;display:block;cursor:default;content:" ";background:transparent}.details-overlay-dark[open]>summary::before{z-index:99;background:rgba(27,31,35,0.5)}.flex-row{flex-direction:row !important}.flex-row-reverse{flex-direction:row-reverse !important}.flex-column{flex-direction:column !important}.flex-wrap{flex-wrap:wrap !important}.flex-nowrap{flex-wrap:nowrap !important}.flex-justify-start{justify-content:flex-start !important}.flex-justify-end{justify-content:flex-end !important}.flex-justify-center{justify-content:center !important}.flex-justify-between{justify-content:space-between !important}.flex-justify-around{justify-content:space-around !important}.flex-items-start{align-items:flex-start !important}.flex-items-end{align-items:flex-end !important}.flex-items-center{align-items:center !important}.flex-items-baseline{align-items:baseline !important}.flex-items-stretch{align-items:stretch !important}.flex-content-start{align-content:flex-start !important}.flex-content-end{align-content:flex-end !important}.flex-content-center{align-content:center !important}.flex-content-between{align-content:space-between !important}.flex-content-around{align-content:space-around !important}.flex-content-stretch{align-content:stretch !important}.flex-auto{flex:1 1 auto !important}.flex-shrink-0{flex-shrink:0 !important}.flex-self-auto{align-self:auto !important}.flex-self-start{align-self:flex-start !important}.flex-self-end{align-self:flex-end !important}.flex-self-center{align-self:center !important}.flex-self-baseline{align-self:baseline !important}.flex-self-stretch{align-self:stretch !important}.flex-item-equal{flex-grow:1;flex-basis:0}@media (min-width: 544px){.flex-sm-row{flex-direction:row !important}.flex-sm-row-reverse{flex-direction:row-reverse !important}.flex-sm-column{flex-direction:column !important}.flex-sm-wrap{flex-wrap:wrap !important}.flex-sm-nowrap{flex-wrap:nowrap !important}.flex-sm-justify-start{justify-content:flex-start !important}.flex-sm-justify-end{justify-content:flex-end !important}.flex-sm-justify-center{justify-content:center !important}.flex-sm-justify-between{justify-content:space-between !important}.flex-sm-justify-around{justify-content:space-around !important}.flex-sm-items-start{align-items:flex-start !important}.flex-sm-items-end{align-items:flex-end !important}.flex-sm-items-center{align-items:center !important}.flex-sm-items-baseline{align-items:baseline !important}.flex-sm-items-stretch{align-items:stretch !important}.flex-sm-content-start{align-content:flex-start !important}.flex-sm-content-end{align-content:flex-end !important}.flex-sm-content-center{align-content:center !important}.flex-sm-content-between{align-content:space-between !important}.flex-sm-content-around{align-content:space-around !important}.flex-sm-content-stretch{align-content:stretch !important}.flex-sm-auto{flex:1 1 auto !important}.flex-sm-shrink-0{flex-shrink:0 !important}.flex-sm-self-auto{align-self:auto !important}.flex-sm-self-start{align-self:flex-start !important}.flex-sm-self-end{align-self:flex-end !important}.flex-sm-self-center{align-self:center !important}.flex-sm-self-baseline{align-self:baseline !important}.flex-sm-self-stretch{align-self:stretch !important}.flex-sm-item-equal{flex-grow:1;flex-basis:0}}@media (min-width: 768px){.flex-md-row{flex-direction:row !important}.flex-md-row-reverse{flex-direction:row-reverse !important}.flex-md-column{flex-direction:column !important}.flex-md-wrap{flex-wrap:wrap !important}.flex-md-nowrap{flex-wrap:nowrap !important}.flex-md-justify-start{justify-content:flex-start !important}.flex-md-justify-end{justify-content:flex-end !important}.flex-md-justify-center{justify-content:center !important}.flex-md-justify-between{justify-content:space-between !important}.flex-md-justify-around{justify-content:space-around !important}.flex-md-items-start{align-items:flex-start !important}.flex-md-items-end{align-items:flex-end !important}.flex-md-items-center{align-items:center !important}.flex-md-items-baseline{align-items:baseline !important}.flex-md-items-stretch{align-items:stretch !important}.flex-md-content-start{align-content:flex-start !important}.flex-md-content-end{align-content:flex-end !important}.flex-md-content-center{align-content:center !important}.flex-md-content-between{align-content:space-between !important}.flex-md-content-around{align-content:space-around !important}.flex-md-content-stretch{align-content:stretch !important}.flex-md-auto{flex:1 1 auto !important}.flex-md-shrink-0{flex-shrink:0 !important}.flex-md-self-auto{align-self:auto !important}.flex-md-self-start{align-self:flex-start !important}.flex-md-self-end{align-self:flex-end !important}.flex-md-self-center{align-self:center !important}.flex-md-self-baseline{align-self:baseline !important}.flex-md-self-stretch{align-self:stretch !important}.flex-md-item-equal{flex-grow:1;flex-basis:0}}@media (min-width: 1012px){.flex-lg-row{flex-direction:row !important}.flex-lg-row-reverse{flex-direction:row-reverse !important}.flex-lg-column{flex-direction:column !important}.flex-lg-wrap{flex-wrap:wrap !important}.flex-lg-nowrap{flex-wrap:nowrap !important}.flex-lg-justify-start{justify-content:flex-start !important}.flex-lg-justify-end{justify-content:flex-end !important}.flex-lg-justify-center{justify-content:center !important}.flex-lg-justify-between{justify-content:space-between !important}.flex-lg-justify-around{justify-content:space-around !important}.flex-lg-items-start{align-items:flex-start !important}.flex-lg-items-end{align-items:flex-end !important}.flex-lg-items-center{align-items:center !important}.flex-lg-items-baseline{align-items:baseline !important}.flex-lg-items-stretch{align-items:stretch !important}.flex-lg-content-start{align-content:flex-start !important}.flex-lg-content-end{align-content:flex-end !important}.flex-lg-content-center{align-content:center !important}.flex-lg-content-between{align-content:space-between !important}.flex-lg-content-around{align-content:space-around !important}.flex-lg-content-stretch{align-content:stretch !important}.flex-lg-auto{flex:1 1 auto !important}.flex-lg-shrink-0{flex-shrink:0 !important}.flex-lg-self-auto{align-self:auto !important}.flex-lg-self-start{align-self:flex-start !important}.flex-lg-self-end{align-self:flex-end !important}.flex-lg-self-center{align-self:center !important}.flex-lg-self-baseline{align-self:baseline !important}.flex-lg-self-stretch{align-self:stretch !important}.flex-lg-item-equal{flex-grow:1;flex-basis:0}}@media (min-width: 1280px){.flex-xl-row{flex-direction:row !important}.flex-xl-row-reverse{flex-direction:row-reverse !important}.flex-xl-column{flex-direction:column !important}.flex-xl-wrap{flex-wrap:wrap !important}.flex-xl-nowrap{flex-wrap:nowrap !important}.flex-xl-justify-start{justify-content:flex-start !important}.flex-xl-justify-end{justify-content:flex-end !important}.flex-xl-justify-center{justify-content:center !important}.flex-xl-justify-between{justify-content:space-between !important}.flex-xl-justify-around{justify-content:space-around !important}.flex-xl-items-start{align-items:flex-start !important}.flex-xl-items-end{align-items:flex-end !important}.flex-xl-items-center{align-items:center !important}.flex-xl-items-baseline{align-items:baseline !important}.flex-xl-items-stretch{align-items:stretch !important}.flex-xl-content-start{align-content:flex-start !important}.flex-xl-content-end{align-content:flex-end !important}.flex-xl-content-center{align-content:center !important}.flex-xl-content-between{align-content:space-between !important}.flex-xl-content-around{align-content:space-around !important}.flex-xl-content-stretch{align-content:stretch !important}.flex-xl-auto{flex:1 1 auto !important}.flex-xl-shrink-0{flex-shrink:0 !important}.flex-xl-self-auto{align-self:auto !important}.flex-xl-self-start{align-self:flex-start !important}.flex-xl-self-end{align-self:flex-end !important}.flex-xl-self-center{align-self:center !important}.flex-xl-self-baseline{align-self:baseline !important}.flex-xl-self-stretch{align-self:stretch !important}.flex-xl-item-equal{flex-grow:1;flex-basis:0}}.position-static{position:static !important}.position-relative{position:relative !important}.position-absolute{position:absolute !important}.position-fixed{position:fixed !important}.top-0{top:0 !important}.right-0{right:0 !important}.bottom-0{bottom:0 !important}.left-0{left:0 !important}.v-align-middle{vertical-align:middle !important}.v-align-top{vertical-align:top !important}.v-align-bottom{vertical-align:bottom !important}.v-align-text-top{vertical-align:text-top !important}.v-align-text-bottom{vertical-align:text-bottom !important}.v-align-baseline{vertical-align:baseline !important}.overflow-hidden{overflow:hidden !important}.overflow-scroll{overflow:scroll !important}.overflow-auto{overflow:auto !important}.clearfix::before{display:table;content:""}.clearfix::after{display:table;clear:both;content:""}.float-left{float:left !important}.float-right{float:right !important}.float-none{float:none !important}@media (min-width: 544px){.float-sm-left{float:left !important}.float-sm-right{float:right !important}.float-sm-none{float:none !important}}@media (min-width: 768px){.float-md-left{float:left !important}.float-md-right{float:right !important}.float-md-none{float:none !important}}@media (min-width: 1012px){.float-lg-left{float:left !important}.float-lg-right{float:right !important}.float-lg-none{float:none !important}}@media (min-width: 1280px){.float-xl-left{float:left !important}.float-xl-right{float:right !important}.float-xl-none{float:none !important}}.width-fit{max-width:100% !important}.width-full{width:100% !important}.height-fit{max-height:100% !important}.height-full{height:100% !important}.min-width-0{min-width:0 !important}.direction-rtl{direction:rtl !important}.direction-ltr{direction:ltr !important}@media (min-width: 544px){.direction-sm-rtl{direction:rtl !important}.direction-sm-ltr{direction:ltr !important}}@media (min-width: 768px){.direction-md-rtl{direction:rtl !important}.direction-md-ltr{direction:ltr !important}}@media (min-width: 1012px){.direction-lg-rtl{direction:rtl !important}.direction-lg-ltr{direction:ltr !important}}@media (min-width: 1280px){.direction-xl-rtl{direction:rtl !important}.direction-xl-ltr{direction:ltr !important}}.m-0{margin:0 !important}.mt-0{margin-top:0 !important}.mr-0{margin-right:0 !important}.mb-0{margin-bottom:0 !important}.ml-0{margin-left:0 !important}.mx-0{margin-right:0 !important;margin-left:0 !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.m-1{margin:4px !important}.mt-1{margin-top:4px !important}.mr-1{margin-right:4px !important}.mb-1{margin-bottom:4px !important}.ml-1{margin-left:4px !important}.mt-n1{margin-top:-4px !important}.mr-n1{margin-right:-4px !important}.mb-n1{margin-bottom:-4px !important}.ml-n1{margin-left:-4px !important}.mx-1{margin-right:4px !important;margin-left:4px !important}.my-1{margin-top:4px !important;margin-bottom:4px !important}.m-2{margin:8px !important}.mt-2{margin-top:8px !important}.mr-2{margin-right:8px !important}.mb-2{margin-bottom:8px !important}.ml-2{margin-left:8px !important}.mt-n2{margin-top:-8px !important}.mr-n2{margin-right:-8px !important}.mb-n2{margin-bottom:-8px !important}.ml-n2{margin-left:-8px !important}.mx-2{margin-right:8px !important;margin-left:8px !important}.my-2{margin-top:8px !important;margin-bottom:8px !important}.m-3{margin:16px !important}.mt-3{margin-top:16px !important}.mr-3{margin-right:16px !important}.mb-3{margin-bottom:16px !important}.ml-3{margin-left:16px !important}.mt-n3{margin-top:-16px !important}.mr-n3{margin-right:-16px !important}.mb-n3{margin-bottom:-16px !important}.ml-n3{margin-left:-16px !important}.mx-3{margin-right:16px !important;margin-left:16px !important}.my-3{margin-top:16px !important;margin-bottom:16px !important}.m-4{margin:24px !important}.mt-4{margin-top:24px !important}.mr-4{margin-right:24px !important}.mb-4{margin-bottom:24px !important}.ml-4{margin-left:24px !important}.mt-n4{margin-top:-24px !important}.mr-n4{margin-right:-24px !important}.mb-n4{margin-bottom:-24px !important}.ml-n4{margin-left:-24px !important}.mx-4{margin-right:24px !important;margin-left:24px !important}.my-4{margin-top:24px !important;margin-bottom:24px !important}.m-5{margin:32px !important}.mt-5{margin-top:32px !important}.mr-5{margin-right:32px !important}.mb-5{margin-bottom:32px !important}.ml-5{margin-left:32px !important}.mt-n5{margin-top:-32px !important}.mr-n5{margin-right:-32px !important}.mb-n5{margin-bottom:-32px !important}.ml-n5{margin-left:-32px !important}.mx-5{margin-right:32px !important;margin-left:32px !important}.my-5{margin-top:32px !important;margin-bottom:32px !important}.m-6{margin:40px !important}.mt-6{margin-top:40px !important}.mr-6{margin-right:40px !important}.mb-6{margin-bottom:40px !important}.ml-6{margin-left:40px !important}.mt-n6{margin-top:-40px !important}.mr-n6{margin-right:-40px !important}.mb-n6{margin-bottom:-40px !important}.ml-n6{margin-left:-40px !important}.mx-6{margin-right:40px !important;margin-left:40px !important}.my-6{margin-top:40px !important;margin-bottom:40px !important}.mx-auto{margin-right:auto !important;margin-left:auto !important}@media (min-width: 544px){.m-sm-0{margin:0 !important}.mt-sm-0{margin-top:0 !important}.mr-sm-0{margin-right:0 !important}.mb-sm-0{margin-bottom:0 !important}.ml-sm-0{margin-left:0 !important}.mx-sm-0{margin-right:0 !important;margin-left:0 !important}.my-sm-0{margin-top:0 !important;margin-bottom:0 !important}.m-sm-1{margin:4px !important}.mt-sm-1{margin-top:4px !important}.mr-sm-1{margin-right:4px !important}.mb-sm-1{margin-bottom:4px !important}.ml-sm-1{margin-left:4px !important}.mt-sm-n1{margin-top:-4px !important}.mr-sm-n1{margin-right:-4px !important}.mb-sm-n1{margin-bottom:-4px !important}.ml-sm-n1{margin-left:-4px !important}.mx-sm-1{margin-right:4px !important;margin-left:4px !important}.my-sm-1{margin-top:4px !important;margin-bottom:4px !important}.m-sm-2{margin:8px !important}.mt-sm-2{margin-top:8px !important}.mr-sm-2{margin-right:8px !important}.mb-sm-2{margin-bottom:8px !important}.ml-sm-2{margin-left:8px !important}.mt-sm-n2{margin-top:-8px !important}.mr-sm-n2{margin-right:-8px !important}.mb-sm-n2{margin-bottom:-8px !important}.ml-sm-n2{margin-left:-8px !important}.mx-sm-2{margin-right:8px !important;margin-left:8px !important}.my-sm-2{margin-top:8px !important;margin-bottom:8px !important}.m-sm-3{margin:16px !important}.mt-sm-3{margin-top:16px !important}.mr-sm-3{margin-right:16px !important}.mb-sm-3{margin-bottom:16px !important}.ml-sm-3{margin-left:16px !important}.mt-sm-n3{margin-top:-16px !important}.mr-sm-n3{margin-right:-16px !important}.mb-sm-n3{margin-bottom:-16px !important}.ml-sm-n3{margin-left:-16px !important}.mx-sm-3{margin-right:16px !important;margin-left:16px !important}.my-sm-3{margin-top:16px !important;margin-bottom:16px !important}.m-sm-4{margin:24px !important}.mt-sm-4{margin-top:24px !important}.mr-sm-4{margin-right:24px !important}.mb-sm-4{margin-bottom:24px !important}.ml-sm-4{margin-left:24px !important}.mt-sm-n4{margin-top:-24px !important}.mr-sm-n4{margin-right:-24px !important}.mb-sm-n4{margin-bottom:-24px !important}.ml-sm-n4{margin-left:-24px !important}.mx-sm-4{margin-right:24px !important;margin-left:24px !important}.my-sm-4{margin-top:24px !important;margin-bottom:24px !important}.m-sm-5{margin:32px !important}.mt-sm-5{margin-top:32px !important}.mr-sm-5{margin-right:32px !important}.mb-sm-5{margin-bottom:32px !important}.ml-sm-5{margin-left:32px !important}.mt-sm-n5{margin-top:-32px !important}.mr-sm-n5{margin-right:-32px !important}.mb-sm-n5{margin-bottom:-32px !important}.ml-sm-n5{margin-left:-32px !important}.mx-sm-5{margin-right:32px !important;margin-left:32px !important}.my-sm-5{margin-top:32px !important;margin-bottom:32px !important}.m-sm-6{margin:40px !important}.mt-sm-6{margin-top:40px !important}.mr-sm-6{margin-right:40px !important}.mb-sm-6{margin-bottom:40px !important}.ml-sm-6{margin-left:40px !important}.mt-sm-n6{margin-top:-40px !important}.mr-sm-n6{margin-right:-40px !important}.mb-sm-n6{margin-bottom:-40px !important}.ml-sm-n6{margin-left:-40px !important}.mx-sm-6{margin-right:40px !important;margin-left:40px !important}.my-sm-6{margin-top:40px !important;margin-bottom:40px !important}.mx-sm-auto{margin-right:auto !important;margin-left:auto !important}}@media (min-width: 768px){.m-md-0{margin:0 !important}.mt-md-0{margin-top:0 !important}.mr-md-0{margin-right:0 !important}.mb-md-0{margin-bottom:0 !important}.ml-md-0{margin-left:0 !important}.mx-md-0{margin-right:0 !important;margin-left:0 !important}.my-md-0{margin-top:0 !important;margin-bottom:0 !important}.m-md-1{margin:4px !important}.mt-md-1{margin-top:4px !important}.mr-md-1{margin-right:4px !important}.mb-md-1{margin-bottom:4px !important}.ml-md-1{margin-left:4px !important}.mt-md-n1{margin-top:-4px !important}.mr-md-n1{margin-right:-4px !important}.mb-md-n1{margin-bottom:-4px !important}.ml-md-n1{margin-left:-4px !important}.mx-md-1{margin-right:4px !important;margin-left:4px !important}.my-md-1{margin-top:4px !important;margin-bottom:4px !important}.m-md-2{margin:8px !important}.mt-md-2{margin-top:8px !important}.mr-md-2{margin-right:8px !important}.mb-md-2{margin-bottom:8px !important}.ml-md-2{margin-left:8px !important}.mt-md-n2{margin-top:-8px !important}.mr-md-n2{margin-right:-8px !important}.mb-md-n2{margin-bottom:-8px !important}.ml-md-n2{margin-left:-8px !important}.mx-md-2{margin-right:8px !important;margin-left:8px !important}.my-md-2{margin-top:8px !important;margin-bottom:8px !important}.m-md-3{margin:16px !important}.mt-md-3{margin-top:16px !important}.mr-md-3{margin-right:16px !important}.mb-md-3{margin-bottom:16px !important}.ml-md-3{margin-left:16px !important}.mt-md-n3{margin-top:-16px !important}.mr-md-n3{margin-right:-16px !important}.mb-md-n3{margin-bottom:-16px !important}.ml-md-n3{margin-left:-16px !important}.mx-md-3{margin-right:16px !important;margin-left:16px !important}.my-md-3{margin-top:16px !important;margin-bottom:16px !important}.m-md-4{margin:24px !important}.mt-md-4{margin-top:24px !important}.mr-md-4{margin-right:24px !important}.mb-md-4{margin-bottom:24px !important}.ml-md-4{margin-left:24px !important}.mt-md-n4{margin-top:-24px !important}.mr-md-n4{margin-right:-24px !important}.mb-md-n4{margin-bottom:-24px !important}.ml-md-n4{margin-left:-24px !important}.mx-md-4{margin-right:24px !important;margin-left:24px !important}.my-md-4{margin-top:24px !important;margin-bottom:24px !important}.m-md-5{margin:32px !important}.mt-md-5{margin-top:32px !important}.mr-md-5{margin-right:32px !important}.mb-md-5{margin-bottom:32px !important}.ml-md-5{margin-left:32px !important}.mt-md-n5{margin-top:-32px !important}.mr-md-n5{margin-right:-32px !important}.mb-md-n5{margin-bottom:-32px !important}.ml-md-n5{margin-left:-32px !important}.mx-md-5{margin-right:32px !important;margin-left:32px !important}.my-md-5{margin-top:32px !important;margin-bottom:32px !important}.m-md-6{margin:40px !important}.mt-md-6{margin-top:40px !important}.mr-md-6{margin-right:40px !important}.mb-md-6{margin-bottom:40px !important}.ml-md-6{margin-left:40px !important}.mt-md-n6{margin-top:-40px !important}.mr-md-n6{margin-right:-40px !important}.mb-md-n6{margin-bottom:-40px !important}.ml-md-n6{margin-left:-40px !important}.mx-md-6{margin-right:40px !important;margin-left:40px !important}.my-md-6{margin-top:40px !important;margin-bottom:40px !important}.mx-md-auto{margin-right:auto !important;margin-left:auto !important}}@media (min-width: 1012px){.m-lg-0{margin:0 !important}.mt-lg-0{margin-top:0 !important}.mr-lg-0{margin-right:0 !important}.mb-lg-0{margin-bottom:0 !important}.ml-lg-0{margin-left:0 !important}.mx-lg-0{margin-right:0 !important;margin-left:0 !important}.my-lg-0{margin-top:0 !important;margin-bottom:0 !important}.m-lg-1{margin:4px !important}.mt-lg-1{margin-top:4px !important}.mr-lg-1{margin-right:4px !important}.mb-lg-1{margin-bottom:4px !important}.ml-lg-1{margin-left:4px !important}.mt-lg-n1{margin-top:-4px !important}.mr-lg-n1{margin-right:-4px !important}.mb-lg-n1{margin-bottom:-4px !important}.ml-lg-n1{margin-left:-4px !important}.mx-lg-1{margin-right:4px !important;margin-left:4px !important}.my-lg-1{margin-top:4px !important;margin-bottom:4px !important}.m-lg-2{margin:8px !important}.mt-lg-2{margin-top:8px !important}.mr-lg-2{margin-right:8px !important}.mb-lg-2{margin-bottom:8px !important}.ml-lg-2{margin-left:8px !important}.mt-lg-n2{margin-top:-8px !important}.mr-lg-n2{margin-right:-8px !important}.mb-lg-n2{margin-bottom:-8px !important}.ml-lg-n2{margin-left:-8px !important}.mx-lg-2{margin-right:8px !important;margin-left:8px !important}.my-lg-2{margin-top:8px !important;margin-bottom:8px !important}.m-lg-3{margin:16px !important}.mt-lg-3{margin-top:16px !important}.mr-lg-3{margin-right:16px !important}.mb-lg-3{margin-bottom:16px !important}.ml-lg-3{margin-left:16px !important}.mt-lg-n3{margin-top:-16px !important}.mr-lg-n3{margin-right:-16px !important}.mb-lg-n3{margin-bottom:-16px !important}.ml-lg-n3{margin-left:-16px !important}.mx-lg-3{margin-right:16px !important;margin-left:16px !important}.my-lg-3{margin-top:16px !important;margin-bottom:16px !important}.m-lg-4{margin:24px !important}.mt-lg-4{margin-top:24px !important}.mr-lg-4{margin-right:24px !important}.mb-lg-4{margin-bottom:24px !important}.ml-lg-4{margin-left:24px !important}.mt-lg-n4{margin-top:-24px !important}.mr-lg-n4{margin-right:-24px !important}.mb-lg-n4{margin-bottom:-24px !important}.ml-lg-n4{margin-left:-24px !important}.mx-lg-4{margin-right:24px !important;margin-left:24px !important}.my-lg-4{margin-top:24px !important;margin-bottom:24px !important}.m-lg-5{margin:32px !important}.mt-lg-5{margin-top:32px !important}.mr-lg-5{margin-right:32px !important}.mb-lg-5{margin-bottom:32px !important}.ml-lg-5{margin-left:32px !important}.mt-lg-n5{margin-top:-32px !important}.mr-lg-n5{margin-right:-32px !important}.mb-lg-n5{margin-bottom:-32px !important}.ml-lg-n5{margin-left:-32px !important}.mx-lg-5{margin-right:32px !important;margin-left:32px !important}.my-lg-5{margin-top:32px !important;margin-bottom:32px !important}.m-lg-6{margin:40px !important}.mt-lg-6{margin-top:40px !important}.mr-lg-6{margin-right:40px !important}.mb-lg-6{margin-bottom:40px !important}.ml-lg-6{margin-left:40px !important}.mt-lg-n6{margin-top:-40px !important}.mr-lg-n6{margin-right:-40px !important}.mb-lg-n6{margin-bottom:-40px !important}.ml-lg-n6{margin-left:-40px !important}.mx-lg-6{margin-right:40px !important;margin-left:40px !important}.my-lg-6{margin-top:40px !important;margin-bottom:40px !important}.mx-lg-auto{margin-right:auto !important;margin-left:auto !important}}@media (min-width: 1280px){.m-xl-0{margin:0 !important}.mt-xl-0{margin-top:0 !important}.mr-xl-0{margin-right:0 !important}.mb-xl-0{margin-bottom:0 !important}.ml-xl-0{margin-left:0 !important}.mx-xl-0{margin-right:0 !important;margin-left:0 !important}.my-xl-0{margin-top:0 !important;margin-bottom:0 !important}.m-xl-1{margin:4px !important}.mt-xl-1{margin-top:4px !important}.mr-xl-1{margin-right:4px !important}.mb-xl-1{margin-bottom:4px !important}.ml-xl-1{margin-left:4px !important}.mt-xl-n1{margin-top:-4px !important}.mr-xl-n1{margin-right:-4px !important}.mb-xl-n1{margin-bottom:-4px !important}.ml-xl-n1{margin-left:-4px !important}.mx-xl-1{margin-right:4px !important;margin-left:4px !important}.my-xl-1{margin-top:4px !important;margin-bottom:4px !important}.m-xl-2{margin:8px !important}.mt-xl-2{margin-top:8px !important}.mr-xl-2{margin-right:8px !important}.mb-xl-2{margin-bottom:8px !important}.ml-xl-2{margin-left:8px !important}.mt-xl-n2{margin-top:-8px !important}.mr-xl-n2{margin-right:-8px !important}.mb-xl-n2{margin-bottom:-8px !important}.ml-xl-n2{margin-left:-8px !important}.mx-xl-2{margin-right:8px !important;margin-left:8px !important}.my-xl-2{margin-top:8px !important;margin-bottom:8px !important}.m-xl-3{margin:16px !important}.mt-xl-3{margin-top:16px !important}.mr-xl-3{margin-right:16px !important}.mb-xl-3{margin-bottom:16px !important}.ml-xl-3{margin-left:16px !important}.mt-xl-n3{margin-top:-16px !important}.mr-xl-n3{margin-right:-16px !important}.mb-xl-n3{margin-bottom:-16px !important}.ml-xl-n3{margin-left:-16px !important}.mx-xl-3{margin-right:16px !important;margin-left:16px !important}.my-xl-3{margin-top:16px !important;margin-bottom:16px !important}.m-xl-4{margin:24px !important}.mt-xl-4{margin-top:24px !important}.mr-xl-4{margin-right:24px !important}.mb-xl-4{margin-bottom:24px !important}.ml-xl-4{margin-left:24px !important}.mt-xl-n4{margin-top:-24px !important}.mr-xl-n4{margin-right:-24px !important}.mb-xl-n4{margin-bottom:-24px !important}.ml-xl-n4{margin-left:-24px !important}.mx-xl-4{margin-right:24px !important;margin-left:24px !important}.my-xl-4{margin-top:24px !important;margin-bottom:24px !important}.m-xl-5{margin:32px !important}.mt-xl-5{margin-top:32px !important}.mr-xl-5{margin-right:32px !important}.mb-xl-5{margin-bottom:32px !important}.ml-xl-5{margin-left:32px !important}.mt-xl-n5{margin-top:-32px !important}.mr-xl-n5{margin-right:-32px !important}.mb-xl-n5{margin-bottom:-32px !important}.ml-xl-n5{margin-left:-32px !important}.mx-xl-5{margin-right:32px !important;margin-left:32px !important}.my-xl-5{margin-top:32px !important;margin-bottom:32px !important}.m-xl-6{margin:40px !important}.mt-xl-6{margin-top:40px !important}.mr-xl-6{margin-right:40px !important}.mb-xl-6{margin-bottom:40px !important}.ml-xl-6{margin-left:40px !important}.mt-xl-n6{margin-top:-40px !important}.mr-xl-n6{margin-right:-40px !important}.mb-xl-n6{margin-bottom:-40px !important}.ml-xl-n6{margin-left:-40px !important}.mx-xl-6{margin-right:40px !important;margin-left:40px !important}.my-xl-6{margin-top:40px !important;margin-bottom:40px !important}.mx-xl-auto{margin-right:auto !important;margin-left:auto !important}}.p-0{padding:0 !important}.pt-0{padding-top:0 !important}.pr-0{padding-right:0 !important}.pb-0{padding-bottom:0 !important}.pl-0{padding-left:0 !important}.px-0{padding-right:0 !important;padding-left:0 !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.p-1{padding:4px !important}.pt-1{padding-top:4px !important}.pr-1{padding-right:4px !important}.pb-1{padding-bottom:4px !important}.pl-1{padding-left:4px !important}.px-1{padding-right:4px !important;padding-left:4px !important}.py-1{padding-top:4px !important;padding-bottom:4px !important}.p-2{padding:8px !important}.pt-2{padding-top:8px !important}.pr-2{padding-right:8px !important}.pb-2{padding-bottom:8px !important}.pl-2{padding-left:8px !important}.px-2{padding-right:8px !important;padding-left:8px !important}.py-2{padding-top:8px !important;padding-bottom:8px !important}.p-3{padding:16px !important}.pt-3{padding-top:16px !important}.pr-3{padding-right:16px !important}.pb-3{padding-bottom:16px !important}.pl-3{padding-left:16px !important}.px-3{padding-right:16px !important;padding-left:16px !important}.py-3{padding-top:16px !important;padding-bottom:16px !important}.p-4{padding:24px !important}.pt-4{padding-top:24px !important}.pr-4{padding-right:24px !important}.pb-4{padding-bottom:24px !important}.pl-4{padding-left:24px !important}.px-4{padding-right:24px !important;padding-left:24px !important}.py-4{padding-top:24px !important;padding-bottom:24px !important}.p-5{padding:32px !important}.pt-5{padding-top:32px !important}.pr-5{padding-right:32px !important}.pb-5{padding-bottom:32px !important}.pl-5{padding-left:32px !important}.px-5{padding-right:32px !important;padding-left:32px !important}.py-5{padding-top:32px !important;padding-bottom:32px !important}.p-6{padding:40px !important}.pt-6{padding-top:40px !important}.pr-6{padding-right:40px !important}.pb-6{padding-bottom:40px !important}.pl-6{padding-left:40px !important}.px-6{padding-right:40px !important;padding-left:40px !important}.py-6{padding-top:40px !important;padding-bottom:40px !important}@media (min-width: 544px){.p-sm-0{padding:0 !important}.pt-sm-0{padding-top:0 !important}.pr-sm-0{padding-right:0 !important}.pb-sm-0{padding-bottom:0 !important}.pl-sm-0{padding-left:0 !important}.px-sm-0{padding-right:0 !important;padding-left:0 !important}.py-sm-0{padding-top:0 !important;padding-bottom:0 !important}.p-sm-1{padding:4px !important}.pt-sm-1{padding-top:4px !important}.pr-sm-1{padding-right:4px !important}.pb-sm-1{padding-bottom:4px !important}.pl-sm-1{padding-left:4px !important}.px-sm-1{padding-right:4px !important;padding-left:4px !important}.py-sm-1{padding-top:4px !important;padding-bottom:4px !important}.p-sm-2{padding:8px !important}.pt-sm-2{padding-top:8px !important}.pr-sm-2{padding-right:8px !important}.pb-sm-2{padding-bottom:8px !important}.pl-sm-2{padding-left:8px !important}.px-sm-2{padding-right:8px !important;padding-left:8px !important}.py-sm-2{padding-top:8px !important;padding-bottom:8px !important}.p-sm-3{padding:16px !important}.pt-sm-3{padding-top:16px !important}.pr-sm-3{padding-right:16px !important}.pb-sm-3{padding-bottom:16px !important}.pl-sm-3{padding-left:16px !important}.px-sm-3{padding-right:16px !important;padding-left:16px !important}.py-sm-3{padding-top:16px !important;padding-bottom:16px !important}.p-sm-4{padding:24px !important}.pt-sm-4{padding-top:24px !important}.pr-sm-4{padding-right:24px !important}.pb-sm-4{padding-bottom:24px !important}.pl-sm-4{padding-left:24px !important}.px-sm-4{padding-right:24px !important;padding-left:24px !important}.py-sm-4{padding-top:24px !important;padding-bottom:24px !important}.p-sm-5{padding:32px !important}.pt-sm-5{padding-top:32px !important}.pr-sm-5{padding-right:32px !important}.pb-sm-5{padding-bottom:32px !important}.pl-sm-5{padding-left:32px !important}.px-sm-5{padding-right:32px !important;padding-left:32px !important}.py-sm-5{padding-top:32px !important;padding-bottom:32px !important}.p-sm-6{padding:40px !important}.pt-sm-6{padding-top:40px !important}.pr-sm-6{padding-right:40px !important}.pb-sm-6{padding-bottom:40px !important}.pl-sm-6{padding-left:40px !important}.px-sm-6{padding-right:40px !important;padding-left:40px !important}.py-sm-6{padding-top:40px !important;padding-bottom:40px !important}}@media (min-width: 768px){.p-md-0{padding:0 !important}.pt-md-0{padding-top:0 !important}.pr-md-0{padding-right:0 !important}.pb-md-0{padding-bottom:0 !important}.pl-md-0{padding-left:0 !important}.px-md-0{padding-right:0 !important;padding-left:0 !important}.py-md-0{padding-top:0 !important;padding-bottom:0 !important}.p-md-1{padding:4px !important}.pt-md-1{padding-top:4px !important}.pr-md-1{padding-right:4px !important}.pb-md-1{padding-bottom:4px !important}.pl-md-1{padding-left:4px !important}.px-md-1{padding-right:4px !important;padding-left:4px !important}.py-md-1{padding-top:4px !important;padding-bottom:4px !important}.p-md-2{padding:8px !important}.pt-md-2{padding-top:8px !important}.pr-md-2{padding-right:8px !important}.pb-md-2{padding-bottom:8px !important}.pl-md-2{padding-left:8px !important}.px-md-2{padding-right:8px !important;padding-left:8px !important}.py-md-2{padding-top:8px !important;padding-bottom:8px !important}.p-md-3{padding:16px !important}.pt-md-3{padding-top:16px !important}.pr-md-3{padding-right:16px !important}.pb-md-3{padding-bottom:16px !important}.pl-md-3{padding-left:16px !important}.px-md-3{padding-right:16px !important;padding-left:16px !important}.py-md-3{padding-top:16px !important;padding-bottom:16px !important}.p-md-4{padding:24px !important}.pt-md-4{padding-top:24px !important}.pr-md-4{padding-right:24px !important}.pb-md-4{padding-bottom:24px !important}.pl-md-4{padding-left:24px !important}.px-md-4{padding-right:24px !important;padding-left:24px !important}.py-md-4{padding-top:24px !important;padding-bottom:24px !important}.p-md-5{padding:32px !important}.pt-md-5{padding-top:32px !important}.pr-md-5{padding-right:32px !important}.pb-md-5{padding-bottom:32px !important}.pl-md-5{padding-left:32px !important}.px-md-5{padding-right:32px !important;padding-left:32px !important}.py-md-5{padding-top:32px !important;padding-bottom:32px !important}.p-md-6{padding:40px !important}.pt-md-6{padding-top:40px !important}.pr-md-6{padding-right:40px !important}.pb-md-6{padding-bottom:40px !important}.pl-md-6{padding-left:40px !important}.px-md-6{padding-right:40px !important;padding-left:40px !important}.py-md-6{padding-top:40px !important;padding-bottom:40px !important}}@media (min-width: 1012px){.p-lg-0{padding:0 !important}.pt-lg-0{padding-top:0 !important}.pr-lg-0{padding-right:0 !important}.pb-lg-0{padding-bottom:0 !important}.pl-lg-0{padding-left:0 !important}.px-lg-0{padding-right:0 !important;padding-left:0 !important}.py-lg-0{padding-top:0 !important;padding-bottom:0 !important}.p-lg-1{padding:4px !important}.pt-lg-1{padding-top:4px !important}.pr-lg-1{padding-right:4px !important}.pb-lg-1{padding-bottom:4px !important}.pl-lg-1{padding-left:4px !important}.px-lg-1{padding-right:4px !important;padding-left:4px !important}.py-lg-1{padding-top:4px !important;padding-bottom:4px !important}.p-lg-2{padding:8px !important}.pt-lg-2{padding-top:8px !important}.pr-lg-2{padding-right:8px !important}.pb-lg-2{padding-bottom:8px !important}.pl-lg-2{padding-left:8px !important}.px-lg-2{padding-right:8px !important;padding-left:8px !important}.py-lg-2{padding-top:8px !important;padding-bottom:8px !important}.p-lg-3{padding:16px !important}.pt-lg-3{padding-top:16px !important}.pr-lg-3{padding-right:16px !important}.pb-lg-3{padding-bottom:16px !important}.pl-lg-3{padding-left:16px !important}.px-lg-3{padding-right:16px !important;padding-left:16px !important}.py-lg-3{padding-top:16px !important;padding-bottom:16px !important}.p-lg-4{padding:24px !important}.pt-lg-4{padding-top:24px !important}.pr-lg-4{padding-right:24px !important}.pb-lg-4{padding-bottom:24px !important}.pl-lg-4{padding-left:24px !important}.px-lg-4{padding-right:24px !important;padding-left:24px !important}.py-lg-4{padding-top:24px !important;padding-bottom:24px !important}.p-lg-5{padding:32px !important}.pt-lg-5{padding-top:32px !important}.pr-lg-5{padding-right:32px !important}.pb-lg-5{padding-bottom:32px !important}.pl-lg-5{padding-left:32px !important}.px-lg-5{padding-right:32px !important;padding-left:32px !important}.py-lg-5{padding-top:32px !important;padding-bottom:32px !important}.p-lg-6{padding:40px !important}.pt-lg-6{padding-top:40px !important}.pr-lg-6{padding-right:40px !important}.pb-lg-6{padding-bottom:40px !important}.pl-lg-6{padding-left:40px !important}.px-lg-6{padding-right:40px !important;padding-left:40px !important}.py-lg-6{padding-top:40px !important;padding-bottom:40px !important}}@media (min-width: 1280px){.p-xl-0{padding:0 !important}.pt-xl-0{padding-top:0 !important}.pr-xl-0{padding-right:0 !important}.pb-xl-0{padding-bottom:0 !important}.pl-xl-0{padding-left:0 !important}.px-xl-0{padding-right:0 !important;padding-left:0 !important}.py-xl-0{padding-top:0 !important;padding-bottom:0 !important}.p-xl-1{padding:4px !important}.pt-xl-1{padding-top:4px !important}.pr-xl-1{padding-right:4px !important}.pb-xl-1{padding-bottom:4px !important}.pl-xl-1{padding-left:4px !important}.px-xl-1{padding-right:4px !important;padding-left:4px !important}.py-xl-1{padding-top:4px !important;padding-bottom:4px !important}.p-xl-2{padding:8px !important}.pt-xl-2{padding-top:8px !important}.pr-xl-2{padding-right:8px !important}.pb-xl-2{padding-bottom:8px !important}.pl-xl-2{padding-left:8px !important}.px-xl-2{padding-right:8px !important;padding-left:8px !important}.py-xl-2{padding-top:8px !important;padding-bottom:8px !important}.p-xl-3{padding:16px !important}.pt-xl-3{padding-top:16px !important}.pr-xl-3{padding-right:16px !important}.pb-xl-3{padding-bottom:16px !important}.pl-xl-3{padding-left:16px !important}.px-xl-3{padding-right:16px !important;padding-left:16px !important}.py-xl-3{padding-top:16px !important;padding-bottom:16px !important}.p-xl-4{padding:24px !important}.pt-xl-4{padding-top:24px !important}.pr-xl-4{padding-right:24px !important}.pb-xl-4{padding-bottom:24px !important}.pl-xl-4{padding-left:24px !important}.px-xl-4{padding-right:24px !important;padding-left:24px !important}.py-xl-4{padding-top:24px !important;padding-bottom:24px !important}.p-xl-5{padding:32px !important}.pt-xl-5{padding-top:32px !important}.pr-xl-5{padding-right:32px !important}.pb-xl-5{padding-bottom:32px !important}.pl-xl-5{padding-left:32px !important}.px-xl-5{padding-right:32px !important;padding-left:32px !important}.py-xl-5{padding-top:32px !important;padding-bottom:32px !important}.p-xl-6{padding:40px !important}.pt-xl-6{padding-top:40px !important}.pr-xl-6{padding-right:40px !important}.pb-xl-6{padding-bottom:40px !important}.pl-xl-6{padding-left:40px !important}.px-xl-6{padding-right:40px !important;padding-left:40px !important}.py-xl-6{padding-top:40px !important;padding-bottom:40px !important}}.p-responsive{padding-right:16px !important;padding-left:16px !important}@media (min-width: 544px){.p-responsive{padding-right:40px !important;padding-left:40px !important}}@media (min-width: 1012px){.p-responsive{padding-right:16px !important;padding-left:16px !important}}.h1{font-size:26px !important}@media (min-width: 768px){.h1{font-size:32px !important}}.h2{font-size:22px !important}@media (min-width: 768px){.h2{font-size:24px !important}}.h3{font-size:18px !important}@media (min-width: 768px){.h3{font-size:20px !important}}.h4{font-size:16px !important}.h5{font-size:14px !important}.h6{font-size:12px !important}.h1,.h2,.h3,.h4,.h5,.h6{font-weight:600 !important}.f1{font-size:26px !important}@media (min-width: 768px){.f1{font-size:32px !important}}.f2{font-size:22px !important}@media (min-width: 768px){.f2{font-size:24px !important}}.f3{font-size:18px !important}@media (min-width: 768px){.f3{font-size:20px !important}}.f4{font-size:16px !important}@media (min-width: 768px){.f4{font-size:16px !important}}.f5{font-size:14px !important}.f6{font-size:12px !important}.f00-light{font-size:40px !important;font-weight:300 !important}@media (min-width: 768px){.f00-light{font-size:48px !important}}.f0-light{font-size:32px !important;font-weight:300 !important}@media (min-width: 768px){.f0-light{font-size:40px !important}}.f1-light{font-size:26px !important;font-weight:300 !important}@media (min-width: 768px){.f1-light{font-size:32px !important}}.f2-light{font-size:22px !important;font-weight:300 !important}@media (min-width: 768px){.f2-light{font-size:24px !important}}.f3-light{font-size:18px !important;font-weight:300 !important}@media (min-width: 768px){.f3-light{font-size:20px !important}}.text-small{font-size:12px !important}.lead{margin-bottom:30px;font-size:20px;font-weight:300;color:#586069}.lh-condensed-ultra{line-height:1 !important}.lh-condensed{line-height:1.25 !important}.lh-default{line-height:1.5 !important}.lh-0{line-height:0 !important}.text-right{text-align:right !important}.text-left{text-align:left !important}.text-center{text-align:center !important}@media (min-width: 544px){.text-sm-right{text-align:right !important}.text-sm-left{text-align:left !important}.text-sm-center{text-align:center !important}}@media (min-width: 768px){.text-md-right{text-align:right !important}.text-md-left{text-align:left !important}.text-md-center{text-align:center !important}}@media (min-width: 1012px){.text-lg-right{text-align:right !important}.text-lg-left{text-align:left !important}.text-lg-center{text-align:center !important}}@media (min-width: 1280px){.text-xl-right{text-align:right !important}.text-xl-left{text-align:left !important}.text-xl-center{text-align:center !important}}.text-normal{font-weight:400 !important}.text-bold{font-weight:600 !important}.text-italic{font-style:italic !important}.text-uppercase{text-transform:uppercase !important}.text-underline{text-decoration:underline !important}.no-underline{text-decoration:none !important}.no-wrap{white-space:nowrap !important}.ws-normal{white-space:normal !important}.wb-break-all{word-break:break-all !important}.text-emphasized{font-weight:600;color:#24292e}.list-style-none{list-style:none !important}.text-shadow-dark{text-shadow:0 1px 1px rgba(27,31,35,0.25),0 1px 25px rgba(27,31,35,0.75)}.text-shadow-light{text-shadow:0 1px 0 rgba(255,255,255,0.5)}.text-mono{font-family:"SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace}.user-select-none{user-select:none !important}.d-block{display:block !important}.d-flex{display:flex !important}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-inline-flex{display:inline-flex !important}.d-none{display:none !important}.d-table{display:table !important}.d-table-cell{display:table-cell !important}@media (min-width: 544px){.d-sm-block{display:block !important}.d-sm-flex{display:flex !important}.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-inline-flex{display:inline-flex !important}.d-sm-none{display:none !important}.d-sm-table{display:table !important}.d-sm-table-cell{display:table-cell !important}}@media (min-width: 768px){.d-md-block{display:block !important}.d-md-flex{display:flex !important}.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-inline-flex{display:inline-flex !important}.d-md-none{display:none !important}.d-md-table{display:table !important}.d-md-table-cell{display:table-cell !important}}@media (min-width: 1012px){.d-lg-block{display:block !important}.d-lg-flex{display:flex !important}.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-inline-flex{display:inline-flex !important}.d-lg-none{display:none !important}.d-lg-table{display:table !important}.d-lg-table-cell{display:table-cell !important}}@media (min-width: 1280px){.d-xl-block{display:block !important}.d-xl-flex{display:flex !important}.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-inline-flex{display:inline-flex !important}.d-xl-none{display:none !important}.d-xl-table{display:table !important}.d-xl-table-cell{display:table-cell !important}}.v-hidden{visibility:hidden !important}.v-visible{visibility:visible !important}@media (max-width: 544px){.hide-sm{display:none !important}}@media (min-width: 544px) and (max-width: 768px){.hide-md{display:none !important}}@media (min-width: 768px) and (max-width: 1012px){.hide-lg{display:none !important}}@media (min-width: 1012px){.hide-xl{display:none !important}}.table-fixed{table-layout:fixed !important}.sr-only{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);word-wrap:normal;border:0}.show-on-focus{position:absolute;width:1px;height:1px;margin:0;overflow:hidden;clip:rect(1px, 1px, 1px, 1px)}.show-on-focus:focus{z-index:20;width:auto;height:auto;clip:auto}.container{width:980px;margin-right:auto;margin-left:auto}.container::before{display:table;content:""}.container::after{display:table;clear:both;content:""}.container-md{max-width:768px;margin-right:auto;margin-left:auto}.container-lg{max-width:1012px;margin-right:auto;margin-left:auto}.container-xl{max-width:1280px;margin-right:auto;margin-left:auto}.columns{margin-right:-10px;margin-left:-10px}.columns::before{display:table;content:""}.columns::after{display:table;clear:both;content:""}.column{float:left;padding-right:10px;padding-left:10px}.one-third{width:33.333333%}.two-thirds{width:66.666667%}.one-fourth{width:25%}.one-half{width:50%}.three-fourths{width:75%}.one-fifth{width:20%}.four-fifths{width:80%}.centered{display:block;float:none;margin-right:auto;margin-left:auto}.col-1{width:8.3333333333%}.col-2{width:16.6666666667%}.col-3{width:25%}.col-4{width:33.3333333333%}.col-5{width:41.6666666667%}.col-6{width:50%}.col-7{width:58.3333333333%}.col-8{width:66.6666666667%}.col-9{width:75%}.col-10{width:83.3333333333%}.col-11{width:91.6666666667%}.col-12{width:100%}@media (min-width: 544px){.col-sm-1{width:8.3333333333%}.col-sm-2{width:16.6666666667%}.col-sm-3{width:25%}.col-sm-4{width:33.3333333333%}.col-sm-5{width:41.6666666667%}.col-sm-6{width:50%}.col-sm-7{width:58.3333333333%}.col-sm-8{width:66.6666666667%}.col-sm-9{width:75%}.col-sm-10{width:83.3333333333%}.col-sm-11{width:91.6666666667%}.col-sm-12{width:100%}}@media (min-width: 768px){.col-md-1{width:8.3333333333%}.col-md-2{width:16.6666666667%}.col-md-3{width:25%}.col-md-4{width:33.3333333333%}.col-md-5{width:41.6666666667%}.col-md-6{width:50%}.col-md-7{width:58.3333333333%}.col-md-8{width:66.6666666667%}.col-md-9{width:75%}.col-md-10{width:83.3333333333%}.col-md-11{width:91.6666666667%}.col-md-12{width:100%}}@media (min-width: 1012px){.col-lg-1{width:8.3333333333%}.col-lg-2{width:16.6666666667%}.col-lg-3{width:25%}.col-lg-4{width:33.3333333333%}.col-lg-5{width:41.6666666667%}.col-lg-6{width:50%}.col-lg-7{width:58.3333333333%}.col-lg-8{width:66.6666666667%}.col-lg-9{width:75%}.col-lg-10{width:83.3333333333%}.col-lg-11{width:91.6666666667%}.col-lg-12{width:100%}}@media (min-width: 1280px){.col-xl-1{width:8.3333333333%}.col-xl-2{width:16.6666666667%}.col-xl-3{width:25%}.col-xl-4{width:33.3333333333%}.col-xl-5{width:41.6666666667%}.col-xl-6{width:50%}.col-xl-7{width:58.3333333333%}.col-xl-8{width:66.6666666667%}.col-xl-9{width:75%}.col-xl-10{width:83.3333333333%}.col-xl-11{width:91.6666666667%}.col-xl-12{width:100%}}.gutter{margin-right:-16px;margin-left:-16px}.gutter>[class*="col-"]{padding-right:16px !important;padding-left:16px !important}.gutter-condensed{margin-right:-8px;margin-left:-8px}.gutter-condensed>[class*="col-"]{padding-right:8px !important;padding-left:8px !important}.gutter-spacious{margin-right:-24px;margin-left:-24px}.gutter-spacious>[class*="col-"]{padding-right:24px !important;padding-left:24px !important}@media (min-width: 544px){.gutter-sm{margin-right:-16px;margin-left:-16px}.gutter-sm>[class*="col-"]{padding-right:16px !important;padding-left:16px !important}.gutter-sm-condensed{margin-right:-8px;margin-left:-8px}.gutter-sm-condensed>[class*="col-"]{padding-right:8px !important;padding-left:8px !important}.gutter-sm-spacious{margin-right:-24px;margin-left:-24px}.gutter-sm-spacious>[class*="col-"]{padding-right:24px !important;padding-left:24px !important}}@media (min-width: 768px){.gutter-md{margin-right:-16px;margin-left:-16px}.gutter-md>[class*="col-"]{padding-right:16px !important;padding-left:16px !important}.gutter-md-condensed{margin-right:-8px;margin-left:-8px}.gutter-md-condensed>[class*="col-"]{padding-right:8px !important;padding-left:8px !important}.gutter-md-spacious{margin-right:-24px;margin-left:-24px}.gutter-md-spacious>[class*="col-"]{padding-right:24px !important;padding-left:24px !important}}@media (min-width: 1012px){.gutter-lg{margin-right:-16px;margin-left:-16px}.gutter-lg>[class*="col-"]{padding-right:16px !important;padding-left:16px !important}.gutter-lg-condensed{margin-right:-8px;margin-left:-8px}.gutter-lg-condensed>[class*="col-"]{padding-right:8px !important;padding-left:8px !important}.gutter-lg-spacious{margin-right:-24px;margin-left:-24px}.gutter-lg-spacious>[class*="col-"]{padding-right:24px !important;padding-left:24px !important}}@media (min-width: 1280px){.gutter-xl{margin-right:-16px;margin-left:-16px}.gutter-xl>[class*="col-"]{padding-right:16px !important;padding-left:16px !important}.gutter-xl-condensed{margin-right:-8px;margin-left:-8px}.gutter-xl-condensed>[class*="col-"]{padding-right:8px !important;padding-left:8px !important}.gutter-xl-spacious{margin-right:-24px;margin-left:-24px}.gutter-xl-spacious>[class*="col-"]{padding-right:24px !important;padding-left:24px !important}}.offset-1{margin-left:8.3333333333% !important}.offset-2{margin-left:16.6666666667% !important}.offset-3{margin-left:25% !important}.offset-4{margin-left:33.3333333333% !important}.offset-5{margin-left:41.6666666667% !important}.offset-6{margin-left:50% !important}.offset-7{margin-left:58.3333333333% !important}.offset-8{margin-left:66.6666666667% !important}.offset-9{margin-left:75% !important}.offset-10{margin-left:83.3333333333% !important}.offset-11{margin-left:91.6666666667% !important}@media (min-width: 544px){.offset-sm-1{margin-left:8.3333333333% !important}.offset-sm-2{margin-left:16.6666666667% !important}.offset-sm-3{margin-left:25% !important}.offset-sm-4{margin-left:33.3333333333% !important}.offset-sm-5{margin-left:41.6666666667% !important}.offset-sm-6{margin-left:50% !important}.offset-sm-7{margin-left:58.3333333333% !important}.offset-sm-8{margin-left:66.6666666667% !important}.offset-sm-9{margin-left:75% !important}.offset-sm-10{margin-left:83.3333333333% !important}.offset-sm-11{margin-left:91.6666666667% !important}}@media (min-width: 768px){.offset-md-1{margin-left:8.3333333333% !important}.offset-md-2{margin-left:16.6666666667% !important}.offset-md-3{margin-left:25% !important}.offset-md-4{margin-left:33.3333333333% !important}.offset-md-5{margin-left:41.6666666667% !important}.offset-md-6{margin-left:50% !important}.offset-md-7{margin-left:58.3333333333% !important}.offset-md-8{margin-left:66.6666666667% !important}.offset-md-9{margin-left:75% !important}.offset-md-10{margin-left:83.3333333333% !important}.offset-md-11{margin-left:91.6666666667% !important}}@media (min-width: 1012px){.offset-lg-1{margin-left:8.3333333333% !important}.offset-lg-2{margin-left:16.6666666667% !important}.offset-lg-3{margin-left:25% !important}.offset-lg-4{margin-left:33.3333333333% !important}.offset-lg-5{margin-left:41.6666666667% !important}.offset-lg-6{margin-left:50% !important}.offset-lg-7{margin-left:58.3333333333% !important}.offset-lg-8{margin-left:66.6666666667% !important}.offset-lg-9{margin-left:75% !important}.offset-lg-10{margin-left:83.3333333333% !important}.offset-lg-11{margin-left:91.6666666667% !important}}@media (min-width: 1280px){.offset-xl-1{margin-left:8.3333333333% !important}.offset-xl-2{margin-left:16.6666666667% !important}.offset-xl-3{margin-left:25% !important}.offset-xl-4{margin-left:33.3333333333% !important}.offset-xl-5{margin-left:41.6666666667% !important}.offset-xl-6{margin-left:50% !important}.offset-xl-7{margin-left:58.3333333333% !important}.offset-xl-8{margin-left:66.6666666667% !important}.offset-xl-9{margin-left:75% !important}.offset-xl-10{margin-left:83.3333333333% !important}.offset-xl-11{margin-left:91.6666666667% !important}}.markdown-body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:16px;line-height:1.5;word-wrap:break-word}.markdown-body::before{display:table;content:""}.markdown-body::after{display:table;clear:both;content:""}.markdown-body>*:first-child{margin-top:0 !important}.markdown-body>*:last-child{margin-bottom:0 !important}.markdown-body a:not([href]){color:inherit;text-decoration:none}.markdown-body .absent{color:#cb2431}.markdown-body .anchor{float:left;padding-right:4px;margin-left:-20px;line-height:1}.markdown-body .anchor:focus{outline:none}.markdown-body p,.markdown-body blockquote,.markdown-body ul,.markdown-body ol,.markdown-body dl,.markdown-body table,.markdown-body pre{margin-top:0;margin-bottom:16px}.markdown-body hr{height:.25em;padding:0;margin:24px 0;background-color:#e1e4e8;border:0}.markdown-body blockquote{padding:0 1em;color:#6a737d;border-left:0.25em solid #dfe2e5}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body kbd{display:inline-block;padding:3px 5px;font-size:11px;line-height:10px;color:#444d56;vertical-align:middle;background-color:#fafbfc;border:solid 1px #c6cbd1;border-bottom-color:#959da5;border-radius:3px;box-shadow:inset 0 -1px 0 #959da5}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:24px;margin-bottom:16px;font-weight:600;line-height:1.25}.markdown-body h1 .octicon-link,.markdown-body h2 .octicon-link,.markdown-body h3 .octicon-link,.markdown-body h4 .octicon-link,.markdown-body h5 .octicon-link,.markdown-body h6 .octicon-link{color:#1b1f23;vertical-align:middle;visibility:hidden}.markdown-body h1:hover .anchor,.markdown-body h2:hover .anchor,.markdown-body h3:hover .anchor,.markdown-body h4:hover .anchor,.markdown-body h5:hover .anchor,.markdown-body h6:hover .anchor{text-decoration:none}.markdown-body h1:hover .anchor .octicon-link,.markdown-body h2:hover .anchor .octicon-link,.markdown-body h3:hover .anchor .octicon-link,.markdown-body h4:hover .anchor .octicon-link,.markdown-body h5:hover .anchor .octicon-link,.markdown-body h6:hover .anchor .octicon-link{visibility:visible}.markdown-body h1 tt,.markdown-body h1 code,.markdown-body h2 tt,.markdown-body h2 code,.markdown-body h3 tt,.markdown-body h3 code,.markdown-body h4 tt,.markdown-body h4 code,.markdown-body h5 tt,.markdown-body h5 code,.markdown-body h6 tt,.markdown-body h6 code{font-size:inherit}.markdown-body h1{padding-bottom:0.3em;font-size:2em;border-bottom:1px solid #eaecef}.markdown-body h2{padding-bottom:0.3em;font-size:1.5em;border-bottom:1px solid #eaecef}.markdown-body h3{font-size:1.25em}.markdown-body h4{font-size:1em}.markdown-body h5{font-size:0.875em}.markdown-body h6{font-size:0.85em;color:#6a737d}.markdown-body ul,.markdown-body ol{padding-left:2em}.markdown-body ul.no-list,.markdown-body ol.no-list{padding:0;list-style-type:none}.markdown-body ul ul,.markdown-body ul ol,.markdown-body ol ol,.markdown-body ol ul{margin-top:0;margin-bottom:0}.markdown-body li{word-wrap:break-all}.markdown-body li>p{margin-top:16px}.markdown-body li+li{margin-top:.25em}.markdown-body dl{padding:0}.markdown-body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:600}.markdown-body dl dd{padding:0 16px;margin-bottom:16px}.markdown-body table{display:block;width:100%;overflow:auto}.markdown-body table th{font-weight:600}.markdown-body table th,.markdown-body table td{padding:6px 13px;border:1px solid #dfe2e5}.markdown-body table tr{background-color:#fff;border-top:1px solid #c6cbd1}.markdown-body table tr:nth-child(2n){background-color:#f6f8fa}.markdown-body table img{background-color:transparent}.markdown-body img{max-width:100%;box-sizing:content-box;background-color:#fff}.markdown-body img[align=right]{padding-left:20px}.markdown-body img[align=left]{padding-right:20px}.markdown-body .emoji{max-width:none;vertical-align:text-top;background-color:transparent}.markdown-body span.frame{display:block;overflow:hidden}.markdown-body span.frame>span{display:block;float:left;width:auto;padding:7px;margin:13px 0 0;overflow:hidden;border:1px solid #dfe2e5}.markdown-body span.frame span img{display:block;float:left}.markdown-body span.frame span span{display:block;padding:5px 0 0;clear:both;color:#24292e}.markdown-body span.align-center{display:block;overflow:hidden;clear:both}.markdown-body span.align-center>span{display:block;margin:13px auto 0;overflow:hidden;text-align:center}.markdown-body span.align-center span img{margin:0 auto;text-align:center}.markdown-body span.align-right{display:block;overflow:hidden;clear:both}.markdown-body span.align-right>span{display:block;margin:13px 0 0;overflow:hidden;text-align:right}.markdown-body span.align-right span img{margin:0;text-align:right}.markdown-body span.float-left{display:block;float:left;margin-right:13px;overflow:hidden}.markdown-body span.float-left span{margin:13px 0 0}.markdown-body span.float-right{display:block;float:right;margin-left:13px;overflow:hidden}.markdown-body span.float-right>span{display:block;margin:13px auto 0;overflow:hidden;text-align:right}.markdown-body code,.markdown-body tt{padding:0.2em 0.4em;margin:0;font-size:85%;background-color:rgba(27,31,35,0.05);border-radius:3px}.markdown-body code br,.markdown-body tt br{display:none}.markdown-body del code{text-decoration:inherit}.markdown-body pre{word-wrap:normal}.markdown-body pre>code{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;background:transparent;border:0}.markdown-body .highlight{margin-bottom:16px}.markdown-body .highlight pre{margin-bottom:0;word-break:normal}.markdown-body .highlight pre,.markdown-body pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f6f8fa;border-radius:3px}.markdown-body pre code,.markdown-body pre tt{display:inline;max-width:auto;padding:0;margin:0;overflow:visible;line-height:inherit;word-wrap:normal;background-color:transparent;border:0}.markdown-body .csv-data td,.markdown-body .csv-data th{padding:5px;overflow:hidden;font-size:12px;line-height:1;text-align:left;white-space:nowrap}.markdown-body .csv-data .blob-num{padding:10px 8px 9px;text-align:right;background:#fff;border:0}.markdown-body .csv-data tr{border-top:0}.markdown-body .csv-data th{font-weight:600;background:#f6f8fa;border-top:0}.highlight table td{padding:5px}.highlight table pre{margin:0}.highlight .cm{color:#999988;font-style:italic}.highlight .cp{color:#999999;font-weight:bold}.highlight .c1{color:#999988;font-style:italic}.highlight .cs{color:#999999;font-weight:bold;font-style:italic}.highlight .c,.highlight .cd{color:#999988;font-style:italic}.highlight .err{color:#a61717;background-color:#e3d2d2}.highlight .gd{color:#000000;background-color:#ffdddd}.highlight .ge{color:#000000;font-style:italic}.highlight .gr{color:#aa0000}.highlight .gh{color:#999999}.highlight .gi{color:#000000;background-color:#ddffdd}.highlight .go{color:#888888}.highlight .gp{color:#555555}.highlight .gs{font-weight:bold}.highlight .gu{color:#aaaaaa}.highlight .gt{color:#aa0000}.highlight .kc{color:#000000;font-weight:bold}.highlight .kd{color:#000000;font-weight:bold}.highlight .kn{color:#000000;font-weight:bold}.highlight .kp{color:#000000;font-weight:bold}.highlight .kr{color:#000000;font-weight:bold}.highlight .kt{color:#445588;font-weight:bold}.highlight .k,.highlight .kv{color:#000000;font-weight:bold}.highlight .mf{color:#009999}.highlight .mh{color:#009999}.highlight .il{color:#009999}.highlight .mi{color:#009999}.highlight .mo{color:#009999}.highlight .m,.highlight .mb,.highlight .mx{color:#009999}.highlight .sb{color:#d14}.highlight .sc{color:#d14}.highlight .sd{color:#d14}.highlight .s2{color:#d14}.highlight .se{color:#d14}.highlight .sh{color:#d14}.highlight .si{color:#d14}.highlight .sx{color:#d14}.highlight .sr{color:#009926}.highlight .s1{color:#d14}.highlight .ss{color:#990073}.highlight .s{color:#d14}.highlight .na{color:#008080}.highlight .bp{color:#999999}.highlight .nb{color:#0086B3}.highlight .nc{color:#445588;font-weight:bold}.highlight .no{color:#008080}.highlight .nd{color:#3c5d5d;font-weight:bold}.highlight .ni{color:#800080}.highlight .ne{color:#990000;font-weight:bold}.highlight .nf{color:#990000;font-weight:bold}.highlight .nl{color:#990000;font-weight:bold}.highlight .nn{color:#555555}.highlight .nt{color:#000080}.highlight .vc{color:#008080}.highlight .vg{color:#008080}.highlight .vi{color:#008080}.highlight .nv{color:#008080}.highlight .ow{color:#000000;font-weight:bold}.highlight .o{color:#000000;font-weight:bold}.highlight .w{color:#bbbbbb}.highlight{background-color:#f8f8f8}.footer{display:none}
img/IBM_card_storage_NARA.jpg

48.9 KiB