LINUX and command line stuff
Published: 2021-09-22 21:13:38

This is really for me, to remember stuff. Based upon [Brian Holt's FrontendMasters course](https://btholt.github.io/complete-intro-to-linux-and-the-cli/):

`echo` prints stuff i.e. echo hi
`--help` flag prints everything about the program i.e. ls --help
`which ls` prints folder where the ls program is stored
`!!`(bangbang) runs the previous command. i.e. pwd and ls -lsah and then you can do `!! && ls -lsah`
`history` prints command history
`.bash_history` file can be found in ~/ (home directory) but for some reason [I cannot see it either](https://askubuntu.com/questions/682243/missing-bash-history). Edit: I didn't see it because it was first session. Subsequent sessions show it because commands in a session are stored in the file after session closes.
`tail ~/.bash_history`

# SHORTCUTS [source: Brian Holt course on FMs](https://btholt.github.io/complete-intro-to-linux-and-the-cli/signals-and-the-power-of-ctrl#shortcuts)

CTRL + A – takes you to the beginning of the line
CTRL + E – takes you to the end of the line
CTRL + K – "yank" everything after the cursor
CTRL + U – "yank" everything before the cursor
CTRL + Y - "paste" (paste in quotes because it doesn't actually go into your system clipboard) everything you yanked
CTRL + L - clear the screen
CTRL + R – reverse search through history

# SIGNALS

`CTRL + C` - SIGINT(errupt)
`CTRL + D` - SIGQUIT

# VIM

`:w` save
`:q` quit
or `:wq`

if you want to quit with unsaved changes: `:q!` (aka the hell outta here)

`:help tutor` (didn't work for me) or (vim adventures](https://vim-adventures.com/) to learn

# FILES

`less textfile.txt` vim like read only view
`man ls` shows manual
`ls --help` abbreviated manual

`cat textfile.txt` like less but without scrolling
`tail textfile.txt` last 10 lines
`mkdir -p my/name/is/brian` creates all the nested directories
`touch` creates new file
`rm`removes file
`rm -r directory_name` removes directory if not empty
`cp {{filename}} {{filename}}` > copies file
`mv {{filename}} {{filename}}` > renames files

# WILDCARDS

`rm *.txt` is the same as `rm file1.txt file2.txt etc`
`ls file*.txt` * replaces anything: 1, 10, etc
`ls file?.txt` ? replaces one char
`ls file[1-3].txt` lists file1, file2 and file3
`ls file[a-c].txt` lists filea, fileb and filec

# EXPANSIONS

`touch file{1..4}.txt` creates file1, file2, file3 and file4
`touch file{a..z}.txt` same
`touch {Aisha,Lanie,Joumana,Krista}-profile.txt`

```
echo {a..z} # prints a to z
echo {z..a} # reverse order
echo {0..100..2} # prints every other (aka even) number from 0 to 100
echo {100..0..5} # prints every 5th number in reverse order from 100 to 0
echo {a..z}{1..5} # prints out a1 a2 a3 a4 a5 b1 b2 b3 <etc>
```

# STREAMS

##stdout

stdout means redirecting the output of a program to another file. like: `ls 1> whatever-file.txt`. if u do `1>>` it will add it to existing content

##stderr

`2>` and `2>>`

## both stdout and stderr

`>` like `cat no-file.txt > error-log.txt`

##stdin

`<` take the content of a file and puts it in stdin so another program can use it

##stdout and stdin

`grep info < file.txt 1> new-file.txt` for instance..

##pipes (use output of one program for another one. previous one refers to files.)

`ls -lsah | grep info` output of one program is used for the next one

# USERS

`whoami`
`cat /etc/passwd` principle of least power
`useradd brian` only superuser can do
`sudo su` change into superuser. sudo = superuser do. switches to root user (terrible idea). u can get out with "exit"
^ su can add users, so can run `useradd {{name}}`
CTRL + D to exit root user (sensible apprach)
`userdel brian`

To change into a user you type: `su {{name of user}}`

```
sudo useradd brian
sudo passwd brian
# make a password, I made something simple like "asdf"
su brian
# your new password
whoami
sudo su
# brian is not in the sudoers file.  This incident will be reported.
```

^ new user can't sudo. We fix it with groups:

`sudo usermod -aG sudo brian` to add brian to the list of users that can sudo. -a === append. -G === groups`

`d rwx rwx rwx` --> 

d / - directory or file
file permission for user that owns the file, for the group that owns the file, for everyone not in the group.
r = read, w = write, x = execute

`chown` change ownership

```
whoami # should say ubuntu
cd /
mkdir hello # permission denied, you don't have permission to do that here
sudo mkdir hello # works, but now hello is owned by root:root
ls -l # notice hello is owned by root:root
touch hello/text.txt # permission denied, you don't own hello
sudo chown ubuntu:ubuntu hello # it's <group>:<user>
ls -l # notice hello is now owned by ubuntu:ubuntu
touch hello/text.txt # works!
```

`chmod` changes mod

```
whoami # should be ubuntu still
cd ~ # go to home directory
sudo touch secret.txt # make a file as root
ls -l secret.txt # -rw-r--r-- so root can read and write but no one else can
echo "very secret message" >> secret.txt # doesn't work, permission denied
sudo chmod u=rw,g=rw,o=rw secret.txt # make it so anyone can read or write to the file
echo "very secret message" >> secret.txt # works this time!
cat secret.txt # should see very secret message
```

or `sudo chmod 666 secret.txt` ^

`chmod +x secret.txt` makes a file executable
`chmod -x secret.txt` removes the executable from a file

# ENVIRONMENTS

`printenv` < prints env variables
`echo $USER`
`USER=brian` < for that particular session

`sudo vi /etc/environment` < u can save new env variables. u need to quit the terminal. any user will have it

`vi ~/.bashrc` > write `export NAME_VARIABLE=bla bla bla` > and then `source ~./.bashrc`
mdifference between .bashrc and .bash_profile? former runs at start of each session. latter runs only first time log in. profile should never be used

# PROCESSES

`ps` < processes run by user only. `PID` means process id.
`ps aux` < aux means all users. that is the difference with `ps`.

`ps aux | grep "ps"` < will find what I am looking for

`kill -9 1783` < kills process 1783 (or `kill -SIGKILL 1783`)

`sleep 10 &` < means wait 10 seconds (sleep 10) and run on the background (&)

background / foreground >> i.e `sleep 10` (foreground) / `sleep 10 &` (background, because of `&`)

`ctrl z` will stop it
`jobs` < show jobs and status

`bg 1` (or whatever the id from jobs) < resumes in the background ie. `sleep 1000 &` . jobs will show sleep -1000 running

`fg 1` will resume it in the foreground

Processes ::> 

if program run succesfully `echo $?` will return 0. If not, it will return something other than 0 (1, 2, 130, etc). Chaining commands like the following will only work if the previous program finished w 0: `touch status.txt && date >> status.txt >> uptime >> status.txt`

(>> means append with a line break at the end)

`touch status.txt || echo lol` means that 2nd command will only run if first didn't finish succesfully

`true ; false ; echo hi` will run the 3 programs no matter what

# SUBCOMMANDS

`echo I think $(whoami) is very cool`
`echo the current date is $(date)`
`echo $(date +%r) - $(uptime) >> log.txt` The `+%x` part is just saying what date of format you want, and I got that from reading `date --help`
`echo $(cat < log.txt) user`

`echo `whoami` hi` 

bacticks is the very old way of doing things

will add the output of whoami in the middle

# SSH

`sudo useradd -s /bin/bash -m -g ubuntu brian`

`-s /bin/bash` will run the bash for this user
`-m` creates home folder for you
`-g` ubuntu gives same permissions as group ubuntu
`brian` is the name of the user

`sudo passwd brian` it changes brian's password

`su brian` changes user to brian

### linking 2 machines with ssh

target machine + machine we will connect from

in primary: `ssh-keygen -t rsa`

generates public and private key. rsa is the flavor of key to be generated. can skip passphrase for now and add default location. creates .ssh folder w id_rsa and id_rsa.pub

in secondary: `mkdir ~/.ssh` we cd into and we type `vi authorized_keys` and we paste the `cat id_rsa.pub` key into that

`chmod 700 ~/.ssh`
`chmod 600 ~/.ssh/authorized_keys`

in secondary

`ifconfig`

will print bunch of stuff, like ip. we grab the inet ip address

in primary: `ssh brian@ip-address`

click `yes`

`exit` to exit console of secondary and retunrn to primary

# SFTP

`sftp brian@ip-address`

`pwd`
`lpwd` is local pwd

`lls` is local ls

`put status.txt`

copies file from primary to secondary server

runing script with ! means on the primary

`!echo lol >> status.txt`
`!cat status.txt`
`put file-to-put.txt yay-new-file.txt` means file gets copied with new name
u can do `ls` in secondary computer and you will see the file

`get` will download files into my primary machine

# WGET

wget -> copy paste of the internet
`wget add_name_file`

# CURL

`curl name_of_file` will print content in screen
`curl name_of_file > game.sh` will add content into file

run python server on ubuntu

`curl http://192.168.64.2:8000` will hit the server and print the response
`curl http://182.168.64.2:8000 > res.txt` will stdout response into the file
`curl -o res2.txt http://...` does the same
`curl -O http://.../output.txt` will write in same file

^ GET

`curl -X POST(or any other verb PUT, etc) http://...`
`curl -d "this is the body" http://...` it is a post because get doesnt have body
`curl -X POST (or PUT orvwhatever) -d "request body" http://...`

send cookies `curl -b "name=brian" -X PATCH http://...`

follow redirect `curl -L http://...` otherwise dorent follow redirect

headers `curl -H "accept-language: en-US" -H "Authorization: Bearer 12345" http://...` add -H for every header that is needed

copy request from browser dev tools : right click on network request, "copy as curl"

# PACKAGE MANAGEMENT

`sudo apt install aptitude` >> is a nice frontend to manage packages
`apt-get` is the old one
`apt` is the new one

`apt install lolcat` wont work bc u dont have permissions
u need to do `sudo apt install lolcat`

`sudo apt install nodejs`

`apt search nodejs`
`apt show nodejs`
`sudo apt autoremove`
`sudo apt update` < gets a new list from apt. doesnt upgrade any package
`apt list` lists all the packages installed
`apt list -upgreadable`
`sudo apt upgrade` < upgrades the packages or one in particular if u do `sudo apt upgrade nodejs` (for example)
`sudo apt full-upgrade`

snap package manager

# SCRIPTS

`vi gen_files.sh`

in vim: `i` (insert mode)
`mkdir -p ~/temp`
`cd ~/temp`
`touch file{1...10}.txt`
`echo done`

to run the file: 

`source gen_files.sh` < changes the directory into /temp
`. gen_files.sh` < change directory. works in more linux distros than source
`bash gen_files.sh` < doesnt change directory

`#!` to interpret the file

file w script can be without extension and first line will be `#! /bin/bash`
then we `chmod +x gen_files` 
`./gen_files` 

it will run

example with node. I need location of node : `which node` will return /snap/bin/node

`vi node_test`

```
#! /snap/bin/node
console.log('running from node')
```

`chmod +x node_test`
`./node_test`

`echo $PATH` will output all the folder paths were programs are located

I need to run `./gen_files` because gen_files alone won't work. for it to work i need to add it to the path. how?

`mkdir my_bin`
`mv gen_files /my_bin`
`vi .bashrc`
at the end we write `export PATH=~/my_bin:$PATH` we restart console

we need full path that is why we add `~` and the `:` allows to attach current path $PATH at the end
echo $PATH will now include `/my_bin` path and u can run `gen_files` without anything else

# VARIABLES IN SCRIPTS

`vi gen_files`

`DESTINATION=~/temp` u can add "" or not its optional if it had spaces you would have to
then u can write `mkdir -p $DESTINATION`
`cd $DESTINATION`
vars font have to be capital case

`FILE_PREFIX=file`
`touch ${FILE_PREFIX}{1..10}.txt curly` braces needed because ambiguous

# USER INPUT

`DESTINATION=$1` means the first argument provided. `$0` is the invocation of the script. and then u continue to use the var `DESTINATION`. or u can use `$1` all across the file. or `$2` for second argument, etc

for the prompt to user to type sth to be used:

`read -p "enter a file prefix: " FILE_PREFIX` the var name is used in the script. `-p` is prompt

```
#! /bin/bash

DESTINATION=~/temp

read -p "enter a file prefix: " FILE_PREFIX

mkdir -p $DESTINATION
cd ~/temp
touch ${FILE_PREFIX}{1..10}.txt
echo done
```

# CONDITIONALS

```
if [ -z $DESTINATION ]; then
     echo "no path provided, defaulting to ~/temp"
     DESTINATION=~/temp
fi
```

`fi` is how if statements end. is if backwards.
`-z` is testing if length of $DESTINATION is zero
`test 15 -eq 15 && echo is true`
`test brian = brian && echo is true`
`test 15 -gt 14 && echo is true`
`-lt`
`-ge`
`-le` less than or equal
`-test -e ~/output.txt && echo is true`
`-e` tests if file exists
`--w` tests if file exists and I can write with the current user

check `man test` for all conditionals

# CASE / ELSE IF

`touch greater-than`
`chmod +x greater-than`
`vi greater-than`

```#! /bin/bash

if [ $1 -gt 10 ]; then 
     echo "greater than ten"
elif [ $1 -lt 10]; then
     echo "less than 10"
else 
     "equals 10"
fi
```

another one:

```
#! /bin/bash

case $1 in
     "smile")
          echo ":)"
          ;;
     "sad")
          echo ":("
          ;;
     "laugh")
          echo ":D"
          ;;
     *)
          echo "I don't know that one yet"
          ;;
esac
```

`esac` is case backwards...     
`*)` means everything else

# ARRAYS

```
#! /bin/bash

friends=(Kyle Marc Jem "Brian Holt" Sarah)

echo My second friend is ${friends[1]}

for friend in ${friends[*]}
do
    echo friend: $friend
done

echo "I have ${#friends[*]} friends"
```

# WHILE

```
#! /bin/bash

# let "NUM_TO_GUESS = ${RANDOM} % 10 + 1"
NUM_TO_GUESS=$(( $RANDOM % 10 + 1 ))
GUESSED_NUM=0

echo "guess a number between 1 and 10"

while [ $NUM_TO_GUESS -ne $GUESSED_NUM ]
do
  read -p "your guess: " GUESSED_NUM
done

echo "you got it!"
```

`-ne` means not equal
`-p` stops execution until user inputs. assigns input to variable

# JOBS / CRON

in ubuntu there are cron folders in /etc/ >> cron_daily, cron_hourly, etc. if the script is executable (chmod +x bla bla) and inside that folder it will run. as long as computer is on, of course.

$() in a script runs a sub-script or program inside.

what if I want to run the job (script) every minute? enter crontab!

crontab -e will ask which editor: nano,  vim, etc
choose vi number 2

* * * * * /home/ubuntu/my_bin/make_new_file 

stars check crontab guru website... (@daily, @reboot too) the other is the path to the script (needs to be executable!) it runs the scripts as your user and u can add a root user if needed: sudo crontab -u root -e

# CUSTOMIZE SHELL

`echo $PS1`
`PS1="whatever"`

and whatever will b the prompt :)

read course notes for cooler customisations

how to do colors in echo: `echo -e "this is color \e[32mgreen"`

the `\e[32m` will transform the word into green. useful for scripts wher u need to show pass, test, etc

awesomebash in github for really cool stuff