Development

PhpStorm as diff tool in Sourcetree

I’am using JetBrain toolbox and this is the config I made for Sourcetree to do diff operations on PhpStorm:

First open PhpStorm and create a command line launcher: Tools -> Create command line launcher..

In my case It suggested: /usr/local/bin/pstorm

Next open Sourcetree preferences and in the Diff tab set those values for diff:

  • Visual Diff Tool: Custom..
  • Diff Command: /usr/local/bin/pstorm
  • Arguments: diff $LOCAL $PWD/$REMOTE

Set those values for Merge:

  • Merge Tool: Custom..
  • Merge Command: /usr/local/bin/pstorm
  • Arguments: merge $PWD/$LOCAL $PWD/$REMOTE $PWD/$BASE $PWD/$MERGED

Enjoy!

Customize Metabse UI without modifying the core code

Metabase is a tool that allows everyone in your company to ask questions and learn from data: handy when it comes to generate reports, charts and export them into Excel etc..

While it is a good tool but I lacks easy basic ways to customize its UI without forking the repository.. Here I show a workaround to bypass the Content-Security-Policy header in Metabase that restricts loading external style sheets.

DISCLAIMER: Metabase license doesn’t allow this so please use only on your dev environment for education purposes only or buy a licence.

We will be using the Apache headers module for that so lets enable it in Apache

sudo a2enmod headers

Next we need to configure the virtual host for our Metabase, mine was in:

sudo nano /etc/apache2/sites-available/reports.example.com-le-ssl.conf

Then we need to see the current header set by Metabase by using PostMan and making a get request to: https://reports.example.com/questions

Note down the current “Content-Security-Policy” header and append your style source as in:

# Allow loading styles from my server
Header set Content-Security-Policy "default-src 'none'; script-src 'unsafe-inline' 'unsafe-eval' 'self' https://maps.google.com https://apis.google.com https://www.google-analytics.com https://*.googleapis.com *.gstatic.com ; child-src 'self' https://accounts.google.com; style-src 'unsafe-inline' 'self' fonts.googleapis.com app.example.com; font-src 'self' fonts.gstatic.com themes.googleusercontent.com ; img-src * 'self' data:; connect-src 'self' metabase.us10.list-manage.com"

Check this list for parameters and their meanings.

And insert it to your vhost conf under:

<VirtualHost *:443>
ServerName reports.example.com
<HERE>

Now we will hijack one of the metabase style and append our custom style to it: since/app/dist/styles\.bundle\.css wis the last stye in Metabase I will use it for my hijacking.

Add this to the vhosts:

# RedirectPermanent Stylesheet
RewriteEngine on
RewriteRule "^/app/dist/styles\.bundle\.css$" "https://example.com/resources/css/reports.min.css" [R]

Test the configuration

sudo apache2ctl configtest

Restart the server

sudo service apache2 restart

PHP_CodeSniffer: Code Beautifier and Fixer, Symfony and PhpStorm

PHP_CodeSniffer is a set of two PHP scripts; the main phpcs script that tokenizes PHP, JavaScript and CSS files to detect violations of a defined coding standard, and a second phpcbf (PHP Code Beautifier and Fixer) script to automatically correct coding standard violations. PHP_CodeSniffer is an essential development tool that ensures your code remains clean and consistent.

In this step by step tutorial I show you how I use this tools to setup my PhpStorm development environment.

Requirement

Make sure composer bin is in your $PATH directory: check your current path with echo $PATH

Install PHP_CodeSniffer

If you use Composer, you can install PHP_CodeSniffer system-wide with the following command:
composer global require "squizlabs/php_codesniffer=*"

This will install PHP_CodeSniffer and all its dependencies into the ~/.composer/vendor/ directory and, most importantly, the PHP_CodeSniffer CLI tools are installed into ~/.composer/vendor/bin/.

See if the package is installed globally: composer global show

If you didn’t do it before, simply add ~/.composer/vendor/bin/ to your PATH in your ~/.bash_profile (or ~/.bashrc) like this:

export PATH=~/.composer/vendor/bin:$PATH

Now phpcs and phpcbf are now available on your command line:

phpcs -h

phpcbf -h

To keep your tools up to date, you simply do this:

composer global update

To remove a package, you edit ~/.composer/composer.json and then run composer global update.

Install Symfony code style

As described on the instructions here: Install the coding standard also system-wide:

composer global require --dev escapestudios/symfony2-coding-standard:3.x-dev

Add Symfony code style:

~/.composer/vendor/bin/phpcbf --config-set installed_paths ~/.composer/vendor/escapestudios/symfony2-coding-standard

Check if code style installed:

~/.composer/vendor/bin/phpcbf -i

You should get something like:
The installed coding standards are PEAR, Zend, PSR2, MySource, Squiz, PSR1 and Symfony

Configure PhpStorm

Open the PhpStorm settings and go to Tools => External Tools, and add a new one with this config settings (change your username!):

Name: phpcbf single file
Description: Fix PHP Codesniffer warnings using PHP Code Beautifier and Fixer
Program: /Users/aidrissi/.composer/vendor/bin/phpcbf
Parameters: –report=full –report-file=$ProjectFileDir$/var/logs/phpcbf.log –standard=Symfony $FileDir$/$FileName$
Working directory:  $ProjectFileDir$

PhpStorm settings window: add new external tool

You can assign a keyboard shortcut for this new tool to format the current open document.

Open the settings again and navigate to: Keymap and search for phpcbf-single file and assign your preferred shortcut: In my case I use Command + Shift + B

PhpStorm run window: results of the run tool

Enjoy 🙂

Metabase as a service for Ubuntu

This is how I installed Metabase in Ubuntu using systemd and services: I am using MySQL and configured the service to get started at system boot time and have the possibility to stop it when I want..

Install Metabase

Downloaded the jar file from metabase.com and put it inside /var/www/metabase

wget http://downloads.metabase.com/v0.229.0/metabase.jar -P /var/www/metabase

 

Create the service

sudo nano /etc/systemd/system/metabase.service

 

Paste the following inside this file:

[Unit]
Description=Metabase service
[Service]
User=root
# The configuration file application.properties should be here:
#change this to your workspace
WorkingDirectory=/var/www/metabase
#path to executable: executable is a bash script which calls jar file
ExecStart=/var/www/metabase/metabase
SuccessExitStatus=143
TimeoutStopSec=10
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target

 

Create a Bash Script to call the service

I created the bash file inside my metabase folder:

sudo nano /var/www/metabase/metabase

 

I prefer to use MySQL instead of H2 default database so: I added the necessary environment variables for that in my script.

#!/bin/sh
sudo /usr/bin/java -DMB_DB_TYPE=mysql -DMB_DB_DBNAME=metabase -DMB_DB_PORT=3306 -DMB_DB_USER=<username> -DMB_DB_PASS="<password>" -DMB_DB_HOST=localhost -jar metabase.jar

 

Give it execute permission:

sudo chmod u+x /var/www/metabase/metabase

 

Start the Metabase service

sudo systemctl daemon-reload
sudo systemctl enable metabase.service
sudo systemctl start metabase
sudo systemctl status metabase

Upgrading Metabase

Suppose I want to upgrade to version 0.29.0 then I do the following:

sudo wget http://downloads.metabase.com/v0.29.0/metabase.jar -P /var/www/metabase -O/var/www/metabase/metabase-new.jar && sudo service metabase stop && sudo mv metabase.jar metabase-old.jar && sudo mv metabase-new.jar metabase.jar && sudo service metabase start

Ansible role to generate unlimited SSL certificates

This is the task for SSL generation:

- name: Create ssl directory
  file: path={{params['ssl'].folder}} state=directory group={{ apache_group }} owner={{ apache_user }}
  become: yes

# generate your own: https://deliciousbrains.com/ssl-certificate-authority-for-local-https-development/
- name: Copy CA certificate and CA private key
  copy:
    src: "{{ item }}"
    dest: "{{params['ssl'].folder}}"
    mode: u+rw,g+r,o+r
  with_fileglob:
    - files/*
  become: yes

- name: Creating private keys for hosts
  shell: openssl genrsa -out {{params['ssl'].folder}}/{{ item.host }}.key 2048
  become: yes
  args:
    executable: "/bin/bash"
  with_items: "{{params['vhosts']}}"
  when: item.ssl|default(true)|bool == true

- name: Creating CSR for hosts
  shell: openssl req -new -key {{params['ssl'].folder}}/{{ item.host }}.key -nodes -out {{params['ssl'].folder}}/{{ item.host }}.csr -subj "/C={{params['ssl'].country_name}}/ST={{params['ssl'].state}}/L={{params['ssl'].locality}}/O={{params['ssl'].organization}}/CN={{ item.host }}"
  become: yes
  args:
    executable: "/bin/bash"
  with_items: "{{params['vhosts']}}"
  when: item.ssl|default(true)|bool == true

- name: Generate the Subject Alternative Name (SAN) extension per host
  template:
    src: ssl/extfile.ext
    dest: "{{params['ssl'].folder}}/{{ item.host }}.ext"
  become: yes
  with_items: "{{params['vhosts']}}"
  when: item.ssl|default(true)|bool == true

- name: Create the certificate per host
  shell: openssl x509 -req -in {{params['ssl'].folder}}/{{ item.host }}.csr -CA {{params['ssl'].folder}}/root_certificate_authority.pem -CAkey {{params['ssl'].folder}}/ca_key.key -passin pass:{{params['ssl'].pass_phrase}} -CAcreateserial -out {{params['ssl'].folder}}/{{ item.host }}.crt -days 1825 -sha256 -extfile {{params['ssl'].folder}}/{{ item.host }}.ext
  become: yes
  args:
    executable: "/bin/bash"
  with_items: "{{params['vhosts']}}"
  when: item.ssl|default(true)|bool == true

 

This is the parameters I used:

vhosts:
  - { projectFolder: "mylocalfolder", host: "azul.dev", framework: "symfony", alias: "az" }
ssl:
    pass_phrase: "vagrant"
    folder: "/etc/apache2/ssl"
    country_name: "MA"
    state: "Ouarzazate"
    locality: "Ouarzazate"
    organization: "Tamazgha Ltd"

Install SSL TLS in your development machine

This one took me a lot of time to get my head over!

Introduction

Openssl is a TLS/SSL and crypto library https://www.openssl.org: it has many commands and lot of configuration options.
openssl is a command line tool that can be used for:

  • Creation of key parameters
  • Creation of X.509 certificates, CSRs and CRLs
  • Calculation of message digests
  • Encryption and decryption
  • SSL/TLS client and server tests
  • Handling of S/MIME signed or encrypted mail
  • And more…

Terminology

CA = Certificate Authority: entity that issues digital certificates

CSR = Certificate Signing Request

PKI = Public Key Infrastructure

PEM = Privacy Enhanced Mail

X509 File Extensions

The first thing we have to understand is what each type of file extension is.   There is a lot of confusion about what DER, PEM, CRT, and CER are and many have incorrectly said that they are all interchangeable.  While in certain cases some can be interchanged the best practice is to identify how your certificate is encoded and then label it correctly.  Correctly labeled certificates will be much easier to manipulat

Encodings (also used as extensions)

  • .DER = The DER extension is used for binary DER encoded certificates. These files may also bear the CER or the CRT extension.   Proper English usage would be “I have a DER encoded certificate” not “I have a DER certificate”.
  • .PEM = The PEM extension is used for different types of X.509v3 files which contain ASCII (Base64) armored data prefixed with a “—– BEGIN …” line.

Common Extensions

  • .CRT = The CRT extension is used for certificates. The certificates may be encoded as binary DER or as ASCII PEM. The CER and CRT extensions are nearly synonymous.  Most common among *nix systems
  • CER = alternate form of .crt (Microsoft Convention) You can use MS to convert .crt to .cer (.both DER encoded .cer, or base64[PEM] encoded .cer)  The .cer file extension is also recognized by IE as a command to run a MS cryptoAPI command (specifically rundll32.exe cryptext.dll,CryptExtOpenCER) which displays a dialogue for importing and/or viewing certificate contents.
  • .KEY = The KEY extension is used both for public and private PKCS#8 keys. The keys may be encoded as binary DER or as ASCII PEM.

The only time CRT and CER can safely be interchanged is when the encoding type can be identical.  (ie  PEM encoded CRT = PEM encoded CER)

First lets set up your CA

Create a folder to hold our config and keys: sudo mkdir /etc/apache2/ssl && cd /etc/apache2/ssl

Create a basic configuration file: touch openssl-ca.cnf

Put this inside sudo nano openssl-ca.cnf:

# openssl-ca.cnf

HOME = .
RANDFILE = $ENV::HOME/.rnd

####################################################################
[ ca ]
default_ca = CA_default # The default ca section

[ CA_default ]

default_days = 1000 # how long to certify for
default_crl_days = 30 # how long before next CRL
default_md = sha256 # use public key default MD
preserve = no # keep passed DN ordering

x509_extensions = ca_extensions # The extensions to add to the cert

email_in_dn = no # Don't concat the email in the DN
copy_extensions = copy # Required to copy SANs from CSR to cert

####################################################################
[ req ]
default_bits = 4096
default_keyfile = cakey.pem
distinguished_name = ca_distinguished_name
x509_extensions = ca_extensions
string_mask = utf8only

####################################################################
[ ca_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = MA

stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default =Drâa‐Tafilalet

localityName = Locality Name (eg, city)
localityName_default = Ouarzazate

organizationName = Organization Name (eg, company)
organizationName_default = Test CA, Limited

organizationalUnitName = Organizational Unit (eg, division)
organizationalUnitName_default = Server Research Department

commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default = Test CA

emailAddress = Email Address
emailAddress_default = test@mydomain.dev

####################################################################
[ ca_extensions ]

subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer
basicConstraints = critical, CA:true
keyUsage = keyCertSign, cRLSign

Then, execute the following. The -nodes omits the password or passphrase so you can examine the certificate.

$ openssl req -x509 -config openssl-ca.cnf -newkey rsa:4096 -sha256 -nodes -out cacert.pem -outform PEM

After the command executes, cacert.pem will be your certificate for CA operations, and cakey.pem will be the private key. Recall the private key does not have a password or passphrase.

You can dump the certificate with the following:

$ openssl x509 -in cacert.pem -text -noout

And test its purpose with the following:

$ openssl x509 -purpose -in cacert.pem -inform PEM

Second: lets sign an end entity certificate (a.k.a server or user)

For part two, I’m going to create another conf file that’s easily digestible.

First, touch the openssl-server.cnf (you can make one of these for user certificates also).

$ touch openssl-server.cnf

Then open it and add the following.

#openssl-server.cnf
HOME = .
RANDFILE = $ENV::HOME/.rnd

####################################################################
[ req ]
default_bits = 2048
default_keyfile = serverkey.pem
distinguished_name = server_distinguished_name
req_extensions = server_req_extensions
string_mask = utf8only

####################################################################
[ server_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = US

stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = MD

localityName = Locality Name (eg, city)
localityName_default = Baltimore

organizationName = Organization Name (eg, company)
organizationName_default = Test CA, Limited

commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default = Test CA

emailAddress = Email Address
emailAddress_default = test@mydomain.dev

####################################################################
[ server_req_extensions ]

subjectKeyIdentifier = hash
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
subjectAltName = @alternate_names
nsComment = "OpenSSL Generated Certificate"

####################################################################
[ alternate_names ]

DNS.1 = mydomain.dev
DNS.2 = www.mydomain.dev
DNS.3 = mail.mydomain.dev
DNS.4 = ftp.mydomain.dev

# IPv4 localhost
IP.1 = 127.0.0.1

# IPv6 localhost
IP.2 = ::1

Then, create the server certificate request.

Be sure to omit -x509*. Adding -x509 will create a certifcate, and not a request.
$ openssl req -config openssl-server.cnf -newkey rsa:2048 -sha256 -nodes -out servercert.csr -outform PEM

After this command executes, you will have a request in servercert.csr and a private key in serverkey.pem.

And you can inspect it again.

$ openssl req -text -noout -verify -in servercert.csr

Next, you have to sign it with your CA.

You are almost ready to sign the server’s certificate by your CA. The CA’s openssl-ca.cnf  needs two more sections before issuing the command.

First, open openssl-ca.cnf and add the following two sections:

####################################################################
[ signing_policy ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

####################################################################
[ signing_req ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment

Second, add the following to the [ CA_default ] section of openssl-ca.cnf. I left them out earlier because they can complicate things (they were unused at the time). Now you will see how they are used, so hopefully they will make sense.

base_dir = .
certificate = $base_dir/cacert.pem # The CA certifcate
private_key = $base_dir/cakey.pem # The CA private key
new_certs_dir = $base_dir # Location for new certs after signing
database = $base_dir/index.txt # Database index file
serial = $base_dir/serial.txt # The current serial number

unique_subject = no # Set to 'no' to allow creation of
# several certificates with same subject.

Third, touch index.txt and serial.txt:

$ touch index.txt
$ echo '01' > serial.txt

Then, perform the following:

$ openssl ca -config openssl-ca.cnf -policy signing_policy -extensions signing_req -out servercert.pem -infiles servercert.csr

You should confirm the sign of the certificate.

After the command executes, you will have a freshly minted server certificate in servercert.pem. The private key was created earlier and is available in serverkey.pem .

Finally, you can inspect your freshly minted certificate with the following:
$ openssl x509 -in servercert.pem -text -noout

Add the certification to your virtual host

Edit your virtual host:

sudo nano /etc/apache2/sites-available/mydomain.dev.conf

<VirtualHost *:443>
    ServerName mydomain.dev
    SSLEngine on
    SSLCertificateFile /etc/apache2/ssl/servercert.pem
    SSLCertificateKeyFile /etc/apache2/ssl/serverkey.pem
    SSLCertificateChainFile /etc/apache2/ssl/cacert.pem
    DocumentRoot /var/www/mydomain/web
    <Directory /var/www/mydomain/web>
        AllowOverride None
        Order Allow,Deny
        Allow from All
        <IfModule mod_rewrite.c>
            Options -MultiViews
            RewriteEngine On
            RewriteCond %{REQUEST_FILENAME} !-f
            RewriteRule ^(.*)$ app_dev.php [QSA,L]
            RewriteEngine On
            RewriteCond %{HTTP:Authorization} ^(.*)
            RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
        </IfModule>
    </Directory>
    <Directory /var/www/mydomain/>
        Options FollowSymlinks
    </Directory>
    <Directory /var/www/mydomain/web/bundles>
        <IfModule mod_rewrite.c>
            RewriteEngine Off
        </IfModule>
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/mydomain.dev_error.log
    CustomLog ${APACHE_LOG_DIR}/mydomain.dev_access.log combined
</VirtualHost>

Add the certificate to Google Chrome

See this steps: https://css-tricks.com/trusting-ssl-locally-mac/

  1. Open chrome://settings-frame/
  2. Scroll down the page and click on: Show advanced settings…
  3. Scroll down and open: Manage certificates on the HTTPS/SSL section
  4. The Keychain Access screen will be displayed. Chrome uses the Keychain Access utility built into MAC OS manage digital certificate
  5. Under ‘Keychains’ on the left, select ‘Login’ and click ‘My Certificates’ in the ‘Category’ column.

Final notes

Earlier, you added the following to CA_default: copy_extensions = copy. This copies extension provided by the person making the request.

If you omit copy_extensions = copy, then your server certificate will lack the Subject Alternate Names (SANs) like www.mydomain.dev and mail.mydomain.dev.

If you use copy_extensions = copy but don’t look over the request, then the requester might be able to trick you into signing something like a subordinate root (rather than a server or user certificate). Which means he will be able to mint certificates that chain back to your trusted root. Be sure to verify the request with openssl req -verify before signing.

If you omit unique_subject or set it to yes, then you will only be allowed to create one certificate under the subject’s distinguished name.
unique_subject = yes # Set to 'no' to allow creation of
# several ctificates with same subject.

Trying to create a second certificate while experimenting will result in the following when signing your server’s certificate with the CA’s private key:
Sign the certificate? [y/n]:Y
failed to update database
TXT_DB error number 2

So unique_subject = no is perfect for testing.


If you want to ensure the Organizational Name is consistent between self-signed CAs, Subordinate CA and End-Entity certificates, then add the following to your CA configuration files:
[ policy_match ]
organizationName = match

If you want to allow the Organizational Name to change, then use:
[ policy_match ]
organizationName = supplied


There are other rules concerning the handling of DNS names in X.509/PKIX certificates. Refer to these documents for the rules:

RFC 6797 and RFC 7469 are listed because they are more restrictive than the other RFCs and CA/B documents. RFC’s 6797 and 7469 do not allow an IP address, either.

Thanks to Jeff at stackoverflow for his inspiring post

Linux: awesome helping commands

Some of the commands I often use:

Search all log files for the word debug case insensitive
$ grep -i debug /var/www/html/register_by_email/var/logs/*.log

Delete all files except one:
$ sudo ls | grep -v 000-default.conf | sudo xargs rm

The same but ignore errors:
$ sudo rm /etc/apache2/ssl/*.* &>/dev/null && cd /etc/apache2/sites-available/ && sudo ls | grep -v 000-default.conf | sudo xargs rm &>/dev/null && cd /etc/apache2/sites-enabled/ && sudo ls | grep -v 000-default.conf | sudo xargs rm &>/dev/null

Advanced copy of files using regular expressions: from a folder with csv files named using a date format like DK20170514.csv this command will copy only files with date from 14 may to 12 june.
$ sudo find -regextype posix-extended -regex '.*/??20170(5(1[4-9]|2[0-9])|6(0[0-9]|1[0-2]))\.csv' | xargs cp -t ../../../special/41393/ &>/dev/null

Note the .*/ in the beginning of the regex: find needs this to work!

Watch how crons work
watch -n 0.1 'ls -1 | wc -l'

Copy a log file from remote to local using ssh
scp -i ~/.ssh/abdel some-server:/var/www/html/myapp/var/logs/dev.log local_dev.log

Display end of file: useful for live debugging single or multiple log files
tail -n 4 -f var/logs/*.*

List all users
cut -d: -f1 /etc/passwd
http://www.numediaweb.com/wordpress/wp-admin/profile.php
List apache current user
ps aux | egrep '(apache|httpd)'

Change a user’s password
sudo passwd someuser

List user associated groups: ex. jenkins
grep '^jenkins:' /etc/group

List user groups
id aidrissi

List all groups
cut -d: -f1 /etc/group

Add a user to a group
usermod -a -G examplegroup exampleusername

Change owner of a folder to “me”
sudo chown -R $(whoami) /usr/local/lib/node_modules/
Use this form to change group aswell with -R for recrussive: chown {-R} [user]{:group} [file|directory]

To create a new symlink (will fail if symlink exists already):
ln -s /path/to/file /path/to/symlink

To create or update a symlink:
ln -sf /path/to/file /path/to/symlink

Test mail sending usin ‘mail’ Command:
mail -s "Test Subject" user@example.com < /dev/null

Get current IP using an external server (you can use nslookup example.com)
curl 'http://ipecho.net/plain'; echo

Get current server time:
date '+%A %W %Y %X'

Chmod command: changing file permissions

chmod [who][+,-,=][permissions] filename
[who]: u=>user, g=>group, o=>others, a=>all
[+,-,=]: The + operator grants permissions whereas the – operator takes away permissions. The parameter g=u means grant group permissions to be same as the user’s.

Get the chmod numerical value for a file

stat --format '%a' file.txt

chmod -R +w,g=rw,o-rw, ~/group-project-files/
The -R option applies the modification to the permissions recursively to the directory specified and to all of its contents.

Here is an example of a file permission through octal notation that is equivalent to chmod u=rwx,go=rx.
chmod 750 ~/group-project.txt

List all environement variables
env

Find domain IP:
dig google.com +noall +answer

 

Delete all branches but keep master and develop:
git branch | grep -v "master" | grep -v "develop" | xargs git branch -D

 

Jump to line X in nano editor (In the nano editor: Ctrl+)
nano +10 file.txt

Upload multiple files from gdrive cli into a parent folder
for filename in ./*.*; do gdrive upload --parent GOOGLE_DRIVE_FOLDER_ID_HERE "${filename}"; done

What is eating my disk space?

sudo du -h –max-depth=1 -x