Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Aroonav Mishra 2019-02-05 10:14:39 +05:30
commit da92421948
48 changed files with 2002 additions and 258 deletions

3
.gitignore vendored
View File

@ -1,4 +1,7 @@
*.log
*.pyc *.pyc
.env
.vagrant
MANIFEST MANIFEST
build build
cheat.egg-info cheat.egg-info

View File

@ -83,37 +83,47 @@ with your [dotfiles][].
Configuring Configuring
----------- -----------
### Setting a DEFAULT_CHEAT_DIR ### ### Setting a CHEAT_USER_DIR ###
Personal cheatsheets are saved in the `~/.cheat` directory by default, but you Personal cheatsheets are saved in the `~/.cheat` directory by default, but you
can specify a different default by exporting a `DEFAULT_CHEAT_DIR` environment can specify a different default by exporting a `CHEAT_USER_DIR` environment
variable: variable:
```sh ```sh
export DEFAULT_CHEAT_DIR='/path/to/my/cheats' export CHEAT_USER_DIR='/path/to/my/cheats'
``` ```
### Setting a CHEATPATH ### ### Setting a CHEAT_PATH ###
You can additionally instruct `cheat` to look for cheatsheets in other You can additionally instruct `cheat` to look for cheatsheets in other
directories by exporting a `CHEATPATH` environment variable: directories by exporting a `CHEAT_PATH` environment variable:
```sh ```sh
export CHEATPATH='/path/to/my/cheats' export CHEAT_PATH='/path/to/my/cheats'
``` ```
You may, of course, append multiple directories to your `CHEATPATH`: You may, of course, append multiple directories to your `CHEAT_PATH`:
```sh ```sh
export CHEATPATH="$CHEATPATH:/path/to/more/cheats" export CHEAT_PATH="$CHEAT_PATH:/path/to/more/cheats"
``` ```
You may view which directories are on your `CHEATPATH` with `cheat -d`. You may view which directories are on your `CHEAT_PATH` with `cheat -d`.
### Enabling Syntax Highlighting ### ### Enabling Syntax Highlighting ###
`cheat` can optionally apply syntax highlighting to your cheatsheets. To enable `cheat` can optionally apply syntax highlighting to your cheatsheets. To
syntax highlighting, export a `CHEATCOLORS` environment variable: enable syntax highlighting, export a `CHEAT_COLORS` environment variable:
```sh ```sh
export CHEATCOLORS=true export CHEAT_COLORS=true
```
Note that [pygments][] must be installed on your system for this to work.
`cheat` ships with both light and dark colorschemes to support terminals with
different background colors. A colorscheme may be selected via the
`CHEAT_COLORSCHEME` envvar:
```sh
export CHEAT_COLORSCHEME=light # must be 'light' (default) or 'dark'
``` ```
#### Specifying a Syntax Highlighter #### #### Specifying a Syntax Highlighter ####
@ -134,6 +144,23 @@ WHERE id = 100
If no syntax highlighter is specified, the `bash` highlighter will be used by If no syntax highlighter is specified, the `bash` highlighter will be used by
default. default.
### Enabling Search Match Highlighting ###
`cheat` can optionally be configured to highlight search term matches in search
results. To do so, export a `CHEAT_HIGHLIGHT` environment variable with a value
of one of the following:
- blue
- cyan
- green
- grey
- magenta
- red
- white
- yellow
Note that the `termcolor` module must be installed on your system for this to
work.
See Also: See Also:
--------- ---------
@ -141,8 +168,9 @@ See Also:
- [Related Projects][related-projects] - [Related Projects][related-projects]
[autocompletion]: https://github.com/chrisallenlane/cheat/wiki/Enabling-Command-line-Autocompletion [autocompletion]: https://github.com/cheat/cheat/wiki/Enabling-Command-line-Autocompletion
[dotfiles]: http://dotfiles.github.io/ [dotfiles]: http://dotfiles.github.io/
[gfm]: https://help.github.com/articles/creating-and-highlighting-code-blocks/ [gfm]: https://help.github.com/articles/creating-and-highlighting-code-blocks/
[installing]: https://github.com/chrisallenlane/cheat/wiki/Installing [installing]: https://github.com/cheat/cheat/wiki/Installing
[related-projects]: https://github.com/chrisallenlane/cheat/wiki/Related-Projects [pygments]: http://pygments.org/
[related-projects]: https://github.com/cheat/cheat/wiki/Related-Projects

17
Vagrantfile vendored Normal file
View File

@ -0,0 +1,17 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/bionic64"
config.vm.provider "virtualbox" do |vb|
vb.memory = "512"
end
config.vm.provision "shell", inline: <<-SHELL
sudo apt-get update
sudo apt-get install -y python-pip
su vagrant && sudo -H pip install docopt pygments termcolor flake8
cd /vagrant && sudo python setup.py install
SHELL
end

View File

@ -13,7 +13,7 @@ Usage:
cheat -v cheat -v
Options: Options:
-d --directories List directories on CHEATPATH -d --directories List directories on $CHEAT_PATH
-e --edit Edit cheatsheet -e --edit Edit cheatsheet
-l --list List cheatsheets -l --list List cheatsheets
-s --search Search cheatsheets for <keyword> -s --search Search cheatsheets for <keyword>
@ -35,31 +35,71 @@ Examples:
""" """
# require the dependencies # require the dependencies
from cheat import sheets, sheet from __future__ import print_function
from cheat.utils import colorize from cheat.colorize import Colorize
from cheat.configuration import Configuration
from cheat.sheet import Sheet
from cheat.sheets import Sheets
from cheat.utils import Utils
from docopt import docopt from docopt import docopt
import os
if __name__ == '__main__': if __name__ == '__main__':
# parse the command-line options # parse the command-line options
options = docopt(__doc__, version='cheat 2.2.1') options = docopt(__doc__, version='cheat 2.5.0')
# initialize and validate configs
config = Configuration()
config.validate()
# create the CHEAT_USER_DIR if it does not exist
if not os.path.isdir(config.cheat_user_dir):
try:
os.mkdir(config.cheat_user_dir)
except OSError:
Utils.die("%s %s %s" % (
'Could not create CHEAT_USER_DIR (',
config.cheat_user_dir,
')')
)
# assert that the CHEAT_USER_DIR is readable and writable
if not os.access(config.cheat_user_dir, os.R_OK):
Utils.die("%s %s %s" % (
'The CHEAT_USER_DIR (',
config.cheat_user_dir,
') is not readable')
)
if not os.access(config.cheat_user_dir, os.W_OK):
Utils.die("%s %s %s" % (
'The CHEAT_USER_DIR (',
config.cheat_user_dir,
') is not writeable')
)
# bootsrap
sheets = Sheets(config)
sheet = Sheet(config, sheets)
colorize = Colorize(config)
# list directories # list directories
if options['--directories']: if options['--directories']:
print("\n".join(sheets.paths())) print("\n".join(sheets.directories()))
# list cheatsheets # list cheatsheets
elif options['--list']: elif options['--list']:
print(sheets.list()) print(sheets.list(), end="")
# create/edit cheatsheet # create/edit cheatsheet
elif options['--edit']: elif options['--edit']:
sheet.create_or_edit(options['<cheatsheet>']) sheet.edit(options['<cheatsheet>'])
# search among the cheatsheets # search among the cheatsheets
elif options['--search']: elif options['--search']:
print(colorize(sheets.search(options['<keyword>']))) print(colorize.syntax(sheets.search(options['<keyword>'])), end="")
# print the cheatsheet # print the cheatsheet
else: else:
print(colorize(sheet.read(options['<cheatsheet>']))) print(colorize.syntax(sheet.read(options['<cheatsheet>'])), end="")

View File

@ -1,3 +0,0 @@
from . import sheet
from . import sheets
from . import utils

View File

@ -1,4 +0,0 @@
import os
def sheets_dir():
return os.path.split(__file__)

11
cheat/cheatsheets/cd Normal file
View File

@ -0,0 +1,11 @@
#Go to the given directory
cd path/to/directory
#Go to home directory of current user
cd
#Go up to the parent of the current directory
cd ..
#Go to the previously chosen directory
cd -

View File

@ -15,5 +15,5 @@ convert original-image.jpg -resize 100x converted-image.png
for file in `ls original/image/path/`; for file in `ls original/image/path/`;
do new_path=${file%.*}; do new_path=${file%.*};
new_file=`basename $new_path`; new_file=`basename $new_path`;
convert $file -resize 150 conerted/image/path/$new_file.png; convert $file -resize 150 converted/image/path/$new_file.png;
done done

View File

@ -6,3 +6,6 @@ cp -r ~/Desktop/cruise_pics/ ~/Pictures/
# Create a copy but ask to overwrite if the destination file already exists # Create a copy but ask to overwrite if the destination file already exists
cp -i ~/Desktop/foo.txt ~/Documents/foo.txt cp -i ~/Desktop/foo.txt ~/Documents/foo.txt
# Create a backup file with date
cp foo.txt{,."$(date +%Y%m%d-%H%M%S)"}

View File

@ -29,10 +29,13 @@ curl -C - -o partial_file.zip http://example.com/file.zip
curl -I http://example.com curl -I http://example.com
# Fetch your external IP and network info as JSON # Fetch your external IP and network info as JSON
curl http://ifconfig.me/all/json curl http://ifconfig.me/all.json
# Limit the rate of a download # Limit the rate of a download
curl --limit-rate 1000B -O http://path.to.the/file curl --limit-rate 1000B -O http://path.to.the/file
# Get your global IP # Get your global IP
curl httpbin.org/ip curl httpbin.org/ip
# Get only the HTTP status code
curl -o /dev/null -w '%{http_code}\n' -s -I URL

View File

@ -1,3 +1,8 @@
# Running emacs
GUI mode $ emacs
Terminal mode $ emacs -nw
# Basic usage # Basic usage
Indent Select text then press TAB Indent Select text then press TAB

View File

@ -19,11 +19,11 @@ find ./path/ -name '*.txt' -exec rm '{}' \;
# To find files with extension '.txt' and look for a string into them: # To find files with extension '.txt' and look for a string into them:
find ./path/ -name '*.txt' | xargs grep 'string' find ./path/ -name '*.txt' | xargs grep 'string'
# To find files with size bigger than 5 Mb and sort them by size: # To find files with size bigger than 5 Mebibyte and sort them by size:
find . -size +5M -type f -print0 | xargs -0 ls -Ssh | sort -z find . -size +5M -type f -print0 | xargs -0 ls -Ssh | sort -z
# To find files bigger thank 2 MB and list them: # To find files bigger than 2 Megabyte and list them:
find . -type f -size +20000k -exec ls -lh {} \; | awk '{ print $9 ": " $5 }' find . -type f -size +200000000c -exec ls -lh {} \; | awk '{ print $9 ": " $5 }'
# To find files modified more than 7 days ago and list file information # To find files modified more than 7 days ago and list file information
find . -type f -mtime +7d -ls find . -type f -mtime +7d -ls

View File

@ -10,8 +10,26 @@ do
echo $var echo $var
done done
# loop over all the JPG files in the current directory
for jpg_file in *.jpg
do
echo $jpg_file
done
# loop specified number of times # loop specified number of times
for i in `seq 1 10` for i in `seq 1 10`
do do
echo $i echo $i
done done
# loop specified number of times: the C/C++ style
for ((i=1;i<=10;++i))
do
echo $i
done
# loop specified number of times: the brace expansion
for i in {1..10}
do
echo $i
done

12
cheat/cheatsheets/gyb Normal file
View File

@ -0,0 +1,12 @@
# To estimate the number and the size of all mails on youremail@gmail.com
gyb --email youremail@gmail.com --action estimate
# To backup from youremail@gmail.com to your local-folder
gyb --email youremail@gmail.com --action backup --local-folder "~/MyLocalFolder/"
# To backup from youremail@gmail.com only important or starred emails to the
# default local folder GYB-GMail-Backup-youremail@gmail.com
gyb --email youremail@gmail.com --search "is:important OR is:starred"
# To restore from your local-folder to youremail@gmail.com
gyb --email youremail@gmail.com --action restore --local-folder "~/MyLocalFolder/"

3
cheat/cheatsheets/iconv Normal file
View File

@ -0,0 +1,3 @@
# To convert file (iconv.src) from iso-8859-1 to utf-8 and save to
# /tmp/iconv.out
iconv -f iso-8859-1 -t utf-8 iconv.src -o /tmp/iconv.out

21
cheat/cheatsheets/lsblk Normal file
View File

@ -0,0 +1,21 @@
# Show all available block devices along with their partitioning schemes
lsblk
# To show SCSI devices:
lsblk --scsi
# To show a specific device
lsblk /dev/sda
# To verify TRIM support:
# Check the values of DISC-GRAN (discard granularity) and DISC-MAX (discard max bytes) columns.
# Non-zero values indicate TRIM support
lsblk --discard
# To featch info about filesystems:
lsblk --fs
# For JSON, LIST or TREE output formats use the following flags:
lsblk --json
lsblk --list
lsblk --tree # default view

View File

@ -38,7 +38,7 @@ This is [an example](http://example.com "Title") inline link.
# image # image
![Alt Text](/path/to/file.png) ![Alt Text](/path/to/file.png)
# emphasis # formatting
*em* _em_ *em* _em_
**strong** __strong__ **strong** __strong__
~~strikethrough~~

22
cheat/cheatsheets/mutt Normal file
View File

@ -0,0 +1,22 @@
# Create new mailbox in IMAP
+ When located in mailbox list (c)
shift + C
# Move multiple messages to folder (bulk operations)
1. Select/tag them with alt+'t'
2. ;s in mail inbox overview for bulk operation
# Deleting / Undeleting all messages in mutt
1. In mutts index, hit D (UPPERCASE D)
2. It will prompt you with “Delete messages matching: “
+ enter this string:
~A
3. It should mark all for deletion!
4. Conversely, you can do the same thing with UPPERCASE U to undelete multiple messages.

View File

@ -12,3 +12,6 @@ mv -i ~/Desktop/foo.txt ~/Documents/foo.txt
# Move a file from one place to another but never overwrite anything # Move a file from one place to another but never overwrite anything
# (This will override any previous -f or -i args) # (This will override any previous -f or -i args)
mv -n ~/Desktop/foo.txt ~/Documents/foo.txt mv -n ~/Desktop/foo.txt ~/Documents/foo.txt
# Move listed files to a directory
mv -t ~/Desktop/ file1 file2 file3

View File

@ -29,3 +29,9 @@ UPDATE tbl_name SET col1 = "example";
# Basic DELETE Statement # Basic DELETE Statement
DELETE FROM tbl_name WHERE user = 'jcole'; DELETE FROM tbl_name WHERE user = 'jcole';
# To check stored procedure
SHOW PROCEDURE STATUS;
# To check stored function
SHOW FUNCTION STATUS;

View File

@ -34,7 +34,10 @@ nmcli dev status
# Add a dynamic ethernet connection - parameters: # Add a dynamic ethernet connection - parameters:
# <name> -- the name of the connection # <name> -- the name of the connection
# <iface_name> -- the name of the interface # <iface_name> -- the name of the interface
ncmli con add type ethernet con-name <name> ifname <iface_name> nmcli con add type ethernet con-name <name> ifname <iface_name>
# Import OpenVPN connection settings from file:
nmcli con import type openvpn file <path_to_ovpn_file>
# Bring up the ethernet connection # Bring up the ethernet connection
nmcli con up <name> nmcli con up <name>

View File

@ -27,6 +27,9 @@ pacman -Ql <package name> | sed -n -e 's/.*\/bin\///p' | tail -n +2
# To list explicitly installed packages # To list explicitly installed packages
pacman -Qe pacman -Qe
# To list the top-most recent explicitly installed packages (not in the base groups)
expac --timefmt='%Y-%m-%d %T' '%l\t%n' $(comm -23 <(pacman -Qeq|sort) <(pacman -Qqg base base-devel|sort)) | sort -r | head -20
# To list orphan packages (installed as dependencies and not required anymore) # To list orphan packages (installed as dependencies and not required anymore)
pacman -Qdt pacman -Qdt

8
cheat/cheatsheets/perl Normal file
View File

@ -0,0 +1,8 @@
# To view the perl version:
perl -v
# Replace string "\n" to newline
echo -e "foo\nbar\nbaz" | perl -pe 's/\n/\\n/g;'
# Replace newline with multiple line to space
cat test.txt | perl -0pe "s/test1\ntest2/test1 test2/m"

936
cheat/cheatsheets/r2 Normal file
View File

@ -0,0 +1,936 @@
# Command Line options
-L: List of supported IO plugins
-q: Exit after processing commands
-w: Write mode enabled
-i: Interprets a r2 script
-A: Analize executable at load time (xrefs, etc)
-n: Bare load. Do not load executable info as the entrypoint
-c'cmds': Run r2 and execute commands (eg: r2 -wqc'wx 3c @ main')
-p: Creates a project for the file being analyzed (CC add a comment when opening a file as a project)
-: Opens r2 with the malloc plugin that gives a 512 bytes memory area to play with (size can be changed); Similar to r2 malloc://512
-----------------------------------------------------------------------------------------------------------------------------
# Configuration properties
e: Returs configuration properties
e <property>: Checks a specific property:
e asm.tabs => false
e <property>=<value>: Change property value
e asm.arch=ppc
e? help about a configuration property
e? cmd.stack
# Show comments at right of disassembly if they fit in screen
e asm.cmtright=true
# Shows pseudocode in disassembly. Eg mov eax, str.ok = > eax = str.ok
e asm.pseudo = true
# Display stack and register values on top of disasembly view (visual mode)
e cmd.stack = true
# Solarized theme
eco solarized
# Use UTF-8 to show cool arrows that do not look like crap :)
e scr.utf8 = true
-----------------------------------------------------------------------------------------------------------------------------
# Basic Commands
; Command chaining: x 3;s+3;pi 3;s+3;pxo 4;
| Pipe with shell commands: pd | less
! Run shell commands: !cat /etc/passwd
!! Escapes to shell, run command and pass output to radare buffer
Note: The double exclamation mark tells radare to skip the plugin list to find an IO plugin handling this
command to launch it directly to the shell. A single one will walk through the io plugin list.
` Radare commands: wx `!ragg2 -i exec`
~ grep
~! grep -v
~[n] grep by columns afl~[0]
~:n grep by rows afl~:0
<command>~.. less/more mode
+-------------------------------------------------------------------
pi~mov,eax ; lines with mov or eax
pi~mov&eax ; lines with mov and eax
pi~mov,eax:6 ; 6 first lines with mov or eax
pd 20~call[0]:0 ; grep first column of the first row matching 'call'
+-------------------------------------------------------------------
.cmd Interprets command output
+-------------------------------------------------------------------
is* prints symbolos
.is* interprets output and define the symbols in radare (normally they are already loaded if r2 was not invoked with -n)
+-------------------------------------------------------------------
.. repeats last commands (same as enter \n)
( Used to define and run macros
$ Used to define alias
$$: Resolves to current address
Offsets (@) are absolute, we can use $$ for relative ones @ $$+4
? Evaluate expression
+-------------------------------------------------------------------
[0x00000000]> ? 33 +2
35 0x23 043 0000:0023 35 00100011 35.0 0.000000
Note: | and & need to be escaped
+-------------------------------------------------------------------
?$? Help for variables used in expressions
$$: Here
$s: File size
$b: Block size
$l: Opcode length
$j: When $$ is at a jmp, $j is the address where we are going to jump to
$f: Same for jmp fail address
$m: Opcode memory reference (e.g. mov eax,[0x10] => 0x10)
??? Help for ? command
?i Takes input from stdin. Eg ?i username
?? Result from previous operations
?s from to [step]: Generates sequence from to every
?p: Get physical address for given virtual address
?P: Get virtual address for given physical one
?v Show hex value of math expr
+-------------------------------------------------------------------
?v 0x1625d4ca ^ 0x72ca4247 = 0x64ef968d
?v 0x4141414a - 0x41414140 = 0xa
+-------------------------------------------------------------------
?l str: Returns the length of string
@@: Used for iteractions
+-------------------------------------------------------------------
wx ff @@10 20 30 Writes ff at offsets 10, 20 and 30
wx ff @@`?s 1 10 2` Writes ff at offsets 1, 2 and 3
wx 90 @@ sym.* Writes a nop on every symbol
+-------------------------------------------------------------------
# Positioning
s address: Move cursor to address or symbol
s-5 (5 bytes backwards)
s- undo seek
s+ redo seek
# Block Size
b size: Change block size
# Analyze
aa: Analyze all (fcns + bbs) same that running r2 with -A
ahl <length> <range>: fake opcode length for a range of bytes
ad: Analyze data
ad@rsp (analize the stack)
+ Normal mode
af: Analyze functions
afl: List all functions
number of functions: afl~?
afi: Returns information about the functions we are currently at
afr: Rename function: structure and flag
afr off: Restore function name set by r2
afn: Rename function
afn strlen 0x080483f0
af-: Removes metadata generated by the function analysis
af+: Define a function manually given the start address and length
af+ 0xd6f 403 checker_loop
axt: Returns cross references to (xref to)
axf: Returns cross references from (xref from)
+ Visual mode
d, f: Function analysis
d, u: Remove metadata generated by function analysis
+ Opcode analysis
ao x: Analize x opcodes from current offset
a8 bytes: Analize the instruction represented by specified bytes
# Information
iI: File info
iz: Strings in data section
izz: Strings in the whole binary
iS: Sections
iS~w returns writable sections
is: Symbols
is~FUNC exports
il: Linked libraries
ii: Imports
ie: Entrypoint
+ Mitigations
i~pic : check if the binary has position-independent-code
i~nx : check if the binary has non-executable stack
i~canary : check if the binary has canaries
# Print
psz n @ offset: Print n zero terminated String
px n @ offset: Print hexdump (or just x) of n bytes
pxw n @ offset: Print hexdump of n words
pxw size@offset prints hexadecimal words at address
pd n @ offset: Print n opcodes disassambled
pD n @ offset: Print n bytes disassembled
pi n @ offset: Print n instructions disassambeled (no address, XREFs, etc. just instrunctions)
pdf @ offset: Print disassembled function
pdf~XREF (grep: XREFs)
pdf~call (grep: calls)
pcp n @ offset: Print n bytes in python string output.
pcp 0x20@0x8048550
import struct
buf = struct.pack ("32B",
0x55,0x89,0xe5,0x83,0xzz,0xzz,0xzz,0xzz,0xf0,0x00,0x00,
0x00,0x00,0xc7,0x45,0xf4,0x00,0x00,0x00,0x00,0xeb,0x20,
0xc7,0x44,0x24,0x04,0x01,0x00,0x00,0x00,0xzz,0xzz)
p8 n @ offset: Print n bytes (8bits) (no hexdump)
pv: Print file contents as IDA bar and shows metadata for each byte (flags , ...)
pt: Interpret data as dates
pf: Print with format
pf.: list all formats
p=: Print entropy ascii graph
# Write
wx: Write hex values in current offset
wx 123456
wx ff @ 4
wa: Write assembly
wa jnz 0x400d24
wc: Write cache commit
wv: Writes value doing endian conversion and padding to byte
wo[x]: Write result of operation
wow 11223344 @102!10
write looped value from 102 to 102+10
0x00000066 1122 3344 1122 3344 1122 0000 0000 0000
wox 0x90
XOR the current block with 0x90. Equivalent to wox 0x90 $$!$b (write from current position, a whole block)
wox 67 @4!10
XOR from offset 4 to 10 with value 67
wf file: Writes the content of the file at the current address or specified offset (ASCII characters only)
wF file: Writes the content of the file at the current address or specified offset
wt file [sz]: Write to file (from current seek, blocksize or sz bytes)
Eg: Dump ELF files with wt @@ hit0* (after searching for ELF headers: \x7fELF)
woO 41424344 : get the index in the De Bruijn Pattern of the given word
# Flags
f: List flags
f label @ offset: Define a flag `label` at offset
f str.pass_len @ 0x804999c
f -label: Removes flag
fr: Rename flag
fd: Returns position from nearest flag (looking backwards). Eg => entry+21
fs: Show all flag spaces
fs flagspace: Change to the specified flag space
fe loop and create numbered flags:
1. fs demo_flagspace
2. fe demo_flagspace @@=`pdf~jne[1]`
# Yank & Paste
y n: Copies n bytes from current position
y: Shows yank buffer contentent with address and length where each entry was copied from
yp: Prints yank buffer
yy offset: Paste the contents of the yank buffer at the specified offset
yt n target @ source: Yank to. Copy n bytes fromsource to target address
# Visual Mode
q: Exits visual mode
hjkl: move around (or HJKL) (left-down-up-right)
o: go/seek to given offset
?: Help
.: Seek EIP
<enter>: Follow address of the current jump/call
:cmd: Enter radare commands. Eg: x @ esi
d[f?]: Define cursor as a string, data, code, a function, or simply to undefine it.
dr: Rename a function
df: Define a function
v: Get into the visual code analysis menu to edit/look closely at the current function.
p/P: Rotate print (visualization) modes
hex, the hexadecimal view
disasm, the disassembly listing
Use numbers in [] to follow jump
Use "u" to go back
debug, the debugger
words, the word-hexidecimal view
buf, the C-formatted buffer
annotated, the annotated hexdump.
c: Changes to cursor mode or exits the cursor mode
select: Shift+[hjkl]
i: Insert mode
a: assembly inline
A: Assembly in visual mode
y: Copy
Y: Paste
f: Creates a flag where cursor points to
<tab> in the hexdump view to toggle between hex and strings columns
V: View ascii-art basic block graph of current function
W: WebUI
x, X: XREFs to current function. ("u" to go back)
t: track flags (browse symbols, functions..)
gG: Begging or end of file
HUD
_ Show HUD
backspace: Exits HUD
We can add new commands to HUD in: radare2/shlr/hud/main
;[-]cmt: Add/remove comment
m<char>: Define a bookmark
'<char>: Go to previously defined bookmark
# ROP
/R opcodes: Search opcodes
/R pop,pop,ret
/Rl opcodes: Search opcodes and print them in linear way
/Rl jmp eax,call ebx
/a: Search assembly
/a jmp eax
pda: Returns a library of gadgets that can be use. These gadgets are obtained by disassmbling byte per byte instead of obeying to opcode leng
e search.roplen = 4 (change the depth of the search, to speed-up the hunt)
# Searching
/ bytes: Search bytes
\x7fELF
+-------------------------------------------------------------------
push ebp
mov ebp, esp
Opcodes: 5589e5
/x 5589e5
[# ]hits: 54c0f4 < 0x0804c600 hits = 1
0x08049f70 hit0_0 5589e557565383e4f081ec
0x0804c31a hit0_1 5589e583ec18c704246031
0x0804c353 hit0_2 5589e583ec1889442404c7
0x0804c379 hit0_3 5589e583ec08e87cffffff
0x0804c3a2 hit0_4 5589e583ec18c70424302d
pi 5 @@hit* (Print 5 first instructions of every hit)
+-------------------------------------------------------------------
Its possible to run a command for each hit. Use the cmd.hit property:
e cmd.hit=px
# Comments and defines
Cd [size]: Define as data
C- [size]: Define as code
Cs [size]: Define as String
Cf [size]: Define as struct
We can define structures to be shown in the disassmbly
CC: List all comments or add a new comment in console mode
C* Show all comments/metadata
CC <comment> add new comment
CC- remove comment
# Magic files
pm: Print Magic files analysis
[0x00000000]> pm
0x00000000 1 ELF 32-bit LSB executable, Intel 80386, version 1
/m [magicfile]: Search magic number headers with libmagic
search.align
search.from (0 = beginning)
search.to (0 = end)
search.asmstr
search.in
# Yara
:yara scan
# Zignatures
zg <language> <output file>: Generate signatures
eg: zg go go.z
Run the generated script to load signatures
eg: . go.z
z: To show signatures loaded:
+-------------------------------------------------------------------
r2-(pid2)> pd 35 @ 0x08049adb-10
| 0x08049adb call fcn.0805b030
| fcn.0805b030(unk, unk, unk, unk) ; sign.sign.b.sym.fmt.Println
| 0x08049ae0 add esp, 0xc
| 0x08049ae3 call fcn.08095580
+-------------------------------------------------------------------
# Compare Files
r2 -m 0xf0000 /etc/fstab ; Open source file
o /etc/issue ; Open file2 at offset 0
o ; List both files
cc offset: Diff by columns between current offset address and "offset"
# Graphs
+ Basic block graphs
af: Load function metadata
ag $$ > a.dot: Dump basic block graph to file
ag $$ | xdot: Show current function basic block graph
+ Call graphs
af: Load function metadata
agc $$ > b.dot: Dump basic block graph to file
+ Convert .dot in .png
dot -Tpng -o /tmp/b.png b.dot
+ Generate graph for file
radiff2 -g main crackme.bin crackme.bin > /tmp/a
xdot /tmp/a
# Debugger
+ Start r2 in debugger mode. r2 will fork and attach
r2 -d [pid|cmd|ptrace] (if command contains spaces use quotes: r2 -d "ls /")
ptrace://pid (debug backend does not notice, only access to mapped memory)
+ Pass arguments
r2 -d rarun2 program=pwn1 arg1=$(python exploit.py)
+ Pass stdin
r2 -d rarun2 program=/bin/ls stdin=$(python exploit.py)
+ Commands
do: Reopen program
dp: Shows debugged process, child processes and threads
dc: Continue
dcu <address or symbol>: Continue until symbol (sets bp in address, continua until bp and remove bp)
dc[sfcp]: Continue until syscall(eg: write), fork, call, program address (To exit a library)
ds: Step in
dso: Step out
dss: Skip instruction
dr register=value: Change register value
dr(=)?: Show register values
db address: Sets a breakpoint at address
db sym.main add breakpoint into sym.main
db 0x804800 add breakpoint
db -0x804800 remove breakpoint
dsi (conditional step): Eg: "dsi eax==3,ecx>0"
dbt: Shows backtrace
drr: Display in colors and words all the refs from registers or memory
dm: Shows memory map (* indicates current section)
[0xb776c110]> dm
sys 0x08048000 - 0x08062000 s r-x /usr/bin/ls
sys 0x08062000 - 0x08064000 s rw- /usr/bin/ls
sys 0xb776a000 - 0xb776b000 s r-x [vdso]
sys 0xb776b000 * 0xb778b000 s r-x /usr/lib/ld-2.17.so
sys 0xb778b000 - 0xb778d000 s rw- /usr/lib/ld-2.17.so
sys 0xbfe5d000 - 0xbfe7e000 s rw- [stack]
+ To follow child processes in forks (set-follow-fork-mode in gdb)
dcf until a fork happen then use dp to select what process you want to debug.
+ PEDA like details
drr;pd 10@-10;pxr 40@esp
+ Debug in visual mode
toggl breakpoints with F2
single-step with F7 (s)
step-over with F8 (S)
continue with F9
# WebGUI
=h: Start the server
=H: Start server and browser
# rax2 - Base Conversion
-e: Change endian
-k: random ASCII art to represent a number/hash. Similar to how SSH represents keys
-s: ASCII to hex
rax2 -S hola (from string to hex)
rax2 -s 686f6c61 (from hex to string)
-S: binary to hex (for files)
-N: pack an integer
rax2 -N 0x1234 # \x34\x12\x00\x00
# rahash2 - Entropy, hashes and checksums
-a: Specify the algorithm
-b XXX: Block size
-B: Print all blocks
-a entropy: Show file entropy or entropy per block (-B -b 512 -a entropy)
+ Rot13 with rahash2
rahash2 -E rot -S s:13 -s Hello\n
# radiff2 - File diffing
-s: Calculate text distance from two files.
-d: Delta diffing (For files with different sizes. Its not byte per byte)
-C: Code diffing (instead of data)
+-------------------------------------------------------------------
Diff original and patched on x86_32, using graphdiff algorithm
radiff2 -a x86 -b32 -C original patched
Show differences between original and patched on x86_32
radiff2 -a x86 -b32 original patched :
+-------------------------------------------------------------------
# rasm2 - Assembly/Disasembly
-L: Supported architectures
-a arch instruction: Sets architecture
rasm2 -a x86 'mov eax,30' => b81e000000
-b tam: Sets block size
-d: Disassembly
rasm2 -d b81e000000 => mov eax, 0x1e
-C: Assembly in C output
rasm2 -C 'mov eax,30' => "\xb8\x1e\x00\x00\x00"
-D: Disassemble showing hexpair and opcode
rasm2 -D b81e0000 => 0x00000000 5 b81e000000 mov eax, 0x1e
-f: Read data from file instead of ARG.
-t: Write data to file
+ Disassemble shellcode from hex stdin
+-------------------------------------------------------------------
echo -n "31c048bbd19d9691d08c97ff48f7db53545f995257545eb03b0f05" | rasm2 -a x86 -b 64 -d -
xor eax, eax
movabs rbx, 0xff978cd091969dd1
neg rbx
push rbx
push rsp
pop rdi
cdq
push rdx
push rdi
push rsp
pop rsi
mov al, 0x3b
syscall
+-------------------------------------------------------------------
# rafind2 - Search
-Z: Look for Zero terminated strings
-s str: Look for specifc string
-X: Hex dump around output
+ Search "/bin/sh" in libc
rafind2 -X -s "/bin/sh" /usr/lib/libc.so.6
# ragg2 - Shellcode generator, C/opcode compiler
P: Generate De Bruijn patterns
ragg2 -P 300 -r
-a arch: Configure architecture
-b bits: Specify architecture bits (32/64)
-i shellcode: Specify shellcode to generate
-e encoder: Specify encoder
+ ragg2-cc: Generate shellcode from c
+ Generate a x86, 32 bits exec shellcode
ragg2 -a x86 -b 32 -i exec
# rabin2 - Executable analysis: symbols, imports, strings
-I: Executable information
-C: Returns classes. Useful to list Java Classes
-l: Dynamic linked libraries
-s: Symbols
-z: Strings
# rarun2 - Launcher to run programs with different environments, args, stdin, permissions, fds
r2 -b 32 -d rarun2 program=pwn1 arg1=$(ragg2 -P 300 -r) : runs pwn1 with a De Bruijn Pattern as first argument, inside radare2's debugger, and force 32 bits
r2 -d rarun2 program=/bin/ls stdin=$(python exploit.py) : runs /bin/ls with the output of exploit.py directed to stdin
# ESIL emulation
1) aei: Initialize ESIL VM
2) aeim: Assign ESIL stack
aeim 0xffffd000 0x1000 stack
3) aeip: Program counter to current seek
4) e io.cache=true: Enable caching read/write of virtual memory (Important if self modifying code)
5) aes: Single stepping in emulation mode
+ Toggle IL representation via O in Visual Mode
# ESIL Linear emulation
Find all references to curr. address using linear esil emulation on all imports.
/re$$@@ sym.imp.*
# ESIL IL Representation
op esil
------------
mov =
mul *
div /
and &
neg !
read []
if ?{
add +
sub -
xor ^
or |
cmp ==
write =[]
+ prefix is %
+ carry from bit x -> %cx
+ borrow from bit x -> %bx
+ zero-flag -> %z
+ parity of dst -> %p
+ sign-flag -> %s
+ overflow-flag -> %o
+ BREAK - Stop parsing and emulate next instruction
+ LOOP - restart emulation of instruction
+ GOTO n - jump to n
+ TODO - stop emulation and eprintf("TDOD %s", ins)
x86 ESIL
------------------------------------------------------
mov eax, ebx ebx,eax,=
jz 0xaabbccdd zf,?{,0xaabbccdd,eip,=,}
cmp ecx,edx edx,ecx,==,%z,zf,=,%b32,cf,=,%p,pf,=,%s,sf,=
push ebp 4,esp,-=ebp,esp,=[4]
+ ESIL Doc
https://github.com/radare/radare2book/blob/master/esil.md
# r2pipe commands
+ Invoke r2pipe script via r2 cmdline
[0x00000000]> #!pipe node script.js
[0x00000000]> #!pipe python script.py
+ Good collection:
https://radare.org/get/r2pipe-nn2015.pdf
https://github.com/jpenalbae/r2-scripts
# Parsing ELF
!!! open with r2 -nn
+ Parse 9 program headers (elf_phdr) from curr. seek plus offset 0x40 with temporary block size 0x200 in less mode (~..)
[0x00000000]> pf 9? (elf_phdr)phdr @ $$+0x40!0x200~..
# pf Templates
+ Generate templates for structs/enums with td command
"td enum elf_class {ELFCLASSNONE=0, ELFCLASS32=1, ELFCLASS64=2};"
https://github.com/Maijin/r2-pf-templates/
+ Cast data @ <addr> to <type> and print it
tp <type> = <address>
# r2scapy
r2 -i r2scapy.py dump.bin
[0x00000000]> scapy DNS 0x81de3c 48
DNS(aa=1L, qr=1L, an=DNSRR(rclass=32769, ttl=120, rrname='flashair.local.', rdata='192.168.0.1', type=1), ad=0L, nscount=0, qdcount=1, ns=None, tc=0L, rd=1L, arcount=0, ar=None, opcode=0L, ra=0L, cd=0L, z=0L, rcode=0L, id=0, ancount=1, qd=DNSQR(qclass=32769, qtype=255, qname='flashair.local.'))
+ generate packets with scapy
>>> from scapy.all import *
>>> sr1(IP(dst="8.8.8.8")/UDP(dport=53)/DNS(rd=1,qd=DNSQR(qname="www.thepacketgeek.com")),verbose=0)
# r2m2 -Miasm Intermediate Representation Plugin
+ Assemble and disassemble MIPS32 using rasm2
r2m2$ export R2M2_ARCH=mips32l; rasm2 -a r2m2 'addiu a0, a1, 2' |rasm2 -a r2m2 -d -
ADDIU A0, A1, 0x2
+ Disassemble random MSP430 instructions in r2
r2m2$ R2M2_ARCH=msp430 r2 -a r2m2 -qc 'woR; pd 5' -
0x00000000 07fa and.w R10, R7
0x00000002 47ad dadd.b R13, R7
0x00000004 f05e0778 add.b @R14+, 0x7807(PC)
0x00000008 f46d81ed addc.b @R13+, 0xED81(R4)
0x0000000c 3fdc bis.w @R12+, R15
+ Assemble MIPS32 using rasm2 and display the call graph using r2
r2m2$ R2M2_ARCH=mips32b rasm2 -a r2m2 'j 0x4; nop' -B > j_nop.bin
r2m2$ R2M2_ARCH=mips32b r2 -a r2m2 -qc 'pd 2' j_nop.bin
,=< 0x00000000 0c000001 JAL 0x4
`-> 0x00000004 00000000 NOP
# bin carving with r2
+ Open raw dump
r2 -n dump.bin
+ Searching for magic
[0x00000000]> / \x7fELF
Searching 4 bytes from 0x00000000 to 0x0000002d: 7f 45 4c 46
0x00001340 hit0_0
0x00001744 hit0_1
...
+ Dump 1M with at several hits
[0x00000000]> b 1M
[0x00000000]> wt @@ hit0*
+ Automate it
$ for a in dump.* ; do
sz=`rabin2 -Z $a` # get RBin.filesize
r2 -wnqc"r $sz" $a # resize file
done
http://radare.today/posts/carving-bins/
# r4ge - symbolic execution
+ https://github.com/gast04/r4ge
Usage: https://asciinema.org/a/155856
# r2wiki -Macro for using wiki in commandline
+ https://github.com/securisec/r2wiki
$wiki "query string"

26
cheat/cheatsheets/rcs Normal file
View File

@ -0,0 +1,26 @@
# Initial check-in of file (leaving file active in filesystem)
ci -u <filename>
# Check out with lock
co -l <filename>
# Check in and unlock (leaving file active in filesystem)
ci -u <filename>
# Display version x.y of a file
co -px.y <filename>
# Undo to version x.y (overwrites file active in filesystem with the specified revision)
co -rx.y <filename>
# Diff file active in filesystem and last revision
rcsdiff <filename>
# Diff versions x.y and x.z
rcsdiff -rx.y -rx.z <filename>
# View log of check-ins
rlog <filename>
# Break an RCS lock held by another person on a file
rcs -u <filename>

View File

@ -12,3 +12,6 @@ rsync -auv /src/foo /dest
# Explicitly copy /src/foo to /dest/foo # Explicitly copy /src/foo to /dest/foo
rsync -auv /src/foo/ /dest/foo rsync -auv /src/foo/ /dest/foo
# Copy file from local to remote over ssh with non standard port 1234 to destination folder in remoteuser's home directory
rsync -avz -e "ssh -p1234" /source/file1 remoteuser@X.X.X.X:~/destination/

20
cheat/cheatsheets/scd Normal file
View File

@ -0,0 +1,20 @@
# To index recursively some paths for the very first run:
scd -ar ~/Documents/
# To change to a directory path matching "doc":
scd doc
# To change to a path matching all of "a", "b" and "c":
scd a b c
# To change to a directory path that ends with "ts":
scd "ts$"
# To show selection menu and ranking of 20 most likely directories:
scd -v
# To alias current directory as "xray":
scd --alias=xray
# To jump to a previously defined aliased directory:
scd xray

View File

@ -3,3 +3,6 @@ scp foo.txt user@example.com:remote/dir
# To copy a file from a remote server to your local machine: # To copy a file from a remote server to your local machine:
scp user@example.com:remote/dir/foo.txt local/dir scp user@example.com:remote/dir/foo.txt local/dir
# To scp a file over a SOCKS proxy on localhost and port 9999 (see ssh for tunnel setup):
scp -o "ProxyCommand nc -x 127.0.0.1:9999 -X 4 %h %p" file.txt username@example2.com:/tmp/

View File

@ -15,3 +15,9 @@ sed '/^$/d' file.txt
# To replace newlines in multiple lines # To replace newlines in multiple lines
sed ':a;N;$!ba;s/\n//g' file.txt sed ':a;N;$!ba;s/\n//g' file.txt
# Insert a line before a matching pattern:
sed '/Once upon a time/i\Chapter 1'
# Add a line after a matching pattern:
sed '/happily ever after/a\The end.'

15
cheat/cheatsheets/slurm Normal file
View File

@ -0,0 +1,15 @@
# Submit a new job:
sbatch job.sh
# List all jobs for a user:
squeue -u user_name
# Cancel a job by id or name:
scancel job_id
scancel --name job_name
# List all information for a job:
scontrol show jobid -dd job_id
# Status info for currently running job:
sstat --format=AveCPU,AvePages,AveRSS,AveVMSize,JobID -j job_id --allsteps

98
cheat/cheatsheets/snap Normal file
View File

@ -0,0 +1,98 @@
# To find the `foo` snap:
snap find foo
# To view detailed information about snap `foo`:
snap info foo
# To view all private snaps (must be logged in):
snap find --private
# To install the `foo` snap:
sudo snap install foo
# To install the `foo` snap from the "beta" channel:
sudo snap install foo --channel=beta
# To view installed snaps:
snap list
# To list all revisions of installed snaps:
snap list --all
# To (manually) update all snaps:
sudo snap refresh
# To (manually) update the `foo` snap:
sudo snap refresh foo
# To update the `foo` snap to the "beta" channel:
sudo snap refresh foo --channel=beta
# To revert the `foo` snap to a prior version:
sudo snap revert foo
# To revert the `foo` snap to revision 5:
snap revert foo --revision 5
# To remove the `foo` snap:
sudo snap remove foo
# To log in to snap (must first create account online):
sudo snap login
# To log out of snap:
snap logout
# To view a transaction log summary:
snap changes
# To view details of item 123 in the transaction log:
snap change 123
# To watch transaction 123:
snap watch 123
# To abort transaction 123:
snap abort 123
# To download the `foo` snap (and its assertions) *without* installing it:
snap download foo
# To install the locally-downloaded `foo` snap with assertions:
snap ack foo.assert
snap install foo.snap
# To install the locally-downloaded `foo` snap without assertions:
# NB: this is dangerous, because the integrity of the snap will not be
# verified. You should only do this to test a snap that you are currently
# developing.
snap install --dangerous foo.snap
# To install snap `foo` in "dev mode":
# NB: this is dangerous, and bypasses the snap sandboxing mechanisms
snap install --devmode foo
# To install snap `foo` in "classic mode":
# NB: this is likewise dangerous
snap install --classic foo
# To view available snap interfaces:
snap interfaces
# To connect the `foo:camera` plug to the ubuntu core slot:
snap connect foo:camera :camera
# To disconnect the `foo:camera` plug from the ubuntu core slot:
snap disconnect foo:camera
# To disable the `foo` snap
snap disable foo
# To enable the `foo` snap
snap enable foo
# To set snap `foo`'s `bar` property to 10:
snap set foo bar=10
# To read snap `foo`'s current `bar` property:
snap get foo bar

37
cheat/cheatsheets/socat Normal file
View File

@ -0,0 +1,37 @@
# socat connect to http-server (port 80 on 'butzel.info')
socat TCP4:butzel.info:80 -
# connect to https-server (port 443 on 'butzel.info' with tls)
socat openssl:butzel.info:443 -
# tcp-listener (port 3180), output as hexdump (-x) and fork for new connetions
socat -x tcp-listen:3180,fork -
# practical examples:
# complete real working http-example:
# (sleep is necessary to prevent socat closing socket before data received)
(echo -e "GET / HTTP/1.1\r\nHost: butzel.info\r\n\r" && sleep 1) \
| socat tcp4:butzel.info:80 -
# http to httpS 'Proxy' (for an webserver without TLS-Support)
socat OPENSSL-LISTEN:443,reuseaddr,pf=ip4,fork,cert=server.pem,cafile=client.crt,verify=0 TCP4-CONNECT:127.0.0.1:80
# port forwarding (e.g. own port 3180 to port 22(ssh) on target
socat TCP4-LISTEN:3180,reuseaddr,fork TCP4:butzel.info:ssh
# TOR-forwarding (needs tor-daemon on port 9050 running)
socat tcp4-listen:8080,reuseaddr,fork socks4A:127.0.0.1:t0rhidd3ns3rvice.onion:80,socksport=9050
# network (port 8266) to serial bridge (/dev/ttyUSB0 baudrate: 115200)
socat TCP4-LISTEN:8266,fork,reuseaddr /dev/ttyUSB0,raw,crnl,b115200
# udp to tcp
socat -u udp-recvfrom:1234,fork tcp:localhost:4321
# reverse shell:
socat exec:'bash -i',pty,stderr tcp:remote.butzel.info:3180
# listener for above reverse shell (on remote.butzel.info):
socat file:`tty`,raw,echo=0 tcp-listen:3180
# or: nc -lp 3180

View File

@ -21,7 +21,10 @@ ssh -f -L 8080:remote.example.com:5000 user@personal.server.com -N
ssh -X -t user@example.com 'chromium-browser' ssh -X -t user@example.com 'chromium-browser'
# To create a SOCKS proxy on localhost and port 9999 # To create a SOCKS proxy on localhost and port 9999
ssh -D 9999 user@example.com ssh -qND 9999 user@example.com
# To tunnel an ssh session over the SOCKS proxy on localhost and port 9999
ssh -o "ProxyCommand nc -x 127.0.0.1:9999 -X 4 %h %p" username@example2.com
# -X use an xsession, -C compress data, "-c blowfish" use the encryption blowfish # -X use an xsession, -C compress data, "-c blowfish" use the encryption blowfish
ssh user@example.com -C -c blowfish -X ssh user@example.com -C -c blowfish -X

View File

@ -3,3 +3,6 @@ ls | tee outfile.txt
# To tee stdout and append to a file: # To tee stdout and append to a file:
ls | tee -a outfile.txt ls | tee -a outfile.txt
# To tee stdout to the terminal, and also pipe it into another program for further processing:
ls | tee /dev/tty | xargs printf "\033[1;34m%s\033[m\n"

View File

@ -10,3 +10,7 @@ find -name *.pdf | xargs -I{} rm -rf '{}'
# -n1 => One file by one file. ( -n2 => 2 files by 2 files ) # -n1 => One file by one file. ( -n2 => 2 files by 2 files )
find -name *.pdf | xargs -I{} -n1 echo '&{}=' find -name *.pdf | xargs -I{} -n1 echo '&{}='
# If find returns no result, do not run rm
# This option is a GNU extension.
find -name "*.pdf" | xargs --no-run-if-empty rm

View File

@ -16,5 +16,8 @@ youtube-dl --playlist-start 5 example.com/watch?v=id&list=listid
# To simulate a download with youtube-dl: # To simulate a download with youtube-dl:
youtube-dl -s example.com/watch?v=id youtube-dl -s example.com/watch?v=id
# For all video formats see # To download audio in mp3 format with best quality available
# http://en.wikipedia.org/wiki/YouTube#Quality_and_codecs youtube-dl --extract-audio --audio-format mp3 --audio-quality 0 example.com/watch?v=id
# For all video formats see link below (unfold "Comparison of YouTube media encoding options")
# https://en.wikipedia.org/w/index.php?title=YouTube&oldid=723160791#Quality_and_formats

126
cheat/cheatsheets/zfs Normal file
View File

@ -0,0 +1,126 @@
# WARNING:
# In order to avoid headaches when moving ZFS physical devices around,
# one will be much better served to reference devices by their *immutable*
# ID - as in /dev/disk/by-id/* - rather than their block device name -
# as in /dev/{sd,nvme}* - which is bound to change as per PCI enumeration
# order.
# For the sake of briefness, we'll use the following variables:
# ${device} device (/dev/disk/by-id/${device})
# ${part} partition (/dev/disk/by-id/${part=${device}-part${N}})
# ${pool} ZFS pool (name)
# ${fs_vol} ZFS file system or volume (name)
# ${snapshot} ZFS snapshot (name)
## Pools
# Create a new "RAID-5" (raidz1) pool
# Recommended: use entire devices rather than partitions
zpool create ${pool} raidz1 ${device} ${device} ${device} [...]
# Add 2nd-level "RAID-1" (mirror) ZFS Intent Log (ZIL; synchronous write cache)
# Recommended: use separate, fast, low-latency devices (e.g. NVMe)
zpool add ${pool} log mirror ${part} ${part}
# Add 2nd-level "RAID-0" Adaptive Replacement Cache (ARC; read cache)
# Recommended: use separate, fast, low-latency devices (e.g. NVMe)
zpool add ${pool} cache ${part} ${part} [...]
# Remove log or cache components
zpool remove zfs ${part} [...]
# Import (enable) existing pool from newly connected devices
# Note: this will create the /etc/zfs/zpool.cache devices cache
zpool import -d /dev/disk/by-id -aN
# Import (enable) existing pool using the devices cache
zpool import -c /etc/zfs/zpool.cache -aN
# Export (disable) pool (e.g. before shutdown)
zpool export -a
# List all (imported) pools
zpool list
# See pool status
zpool status ${pool}
# See detailed pool I/O statistics
zpool iostat ${pool} -v
# Verify pool integrity (data checksums)
# (watch progress with 'zpool status')
zpool scrub ${pool}
# Remove a failing device from a pool
# Note: redundant pools (mirror, raidz) will continue working in degraded state
zpool detach ${pool} ${device}
# Replace a failed device in a pool
# Note: new device will be "resilvered" automatically (parity reconstruction)
# (watch progress with 'zpool status')
zpool replace ${pool} ${failed-device} ${new-device}
# Erase zpool labels ("superblock") from a device/partition
# WARNING: MUST do before reusing a device/partition for other purposes
zpool labelclear ${device}
# Query pool configuration (properties)
zpool get all ${pool}
# Change pool configuration (property)
zpool set <property>=<value> ${pool}
# Dump the entire pool (commands) history
zpool history ${pool}
# More...
man zpool
## File systems / Volumes
# Create a new file system
zfs create ${pool}/${fs_vol}
# Create a new volume ("block device")
# Note: look for it in /dev/zvol/${pool}/${fs_vol}
zfs create -V <size> ${pool}/${fs_vol}
# List all file systems / volumes
zfs list
# Mount all file systems
# Note: see 'zfs get mountpoint ${pool}' for mountpoint root path
zfs mount -a
# Create a snapshot
zfs snapshot ${pool}/${fs_vol}@${snapshot}
# Delete a snapshot
zfs destroy ${pool}/${fs_vol}@${snapshot}
# Full backup
# Note: pipe (|) source to destination through netcat, SSH, etc.
# ... on source:
zfs send -p -R ${pool}/${fs_vol}@${snapshot}
# ... on destination:
zfs receive -F ${pool}/${fs_vol}
# Incremental backup
# Note: pipe (|) source to destination through netcat, SSH, etc.
# ... on source:
zfs send -p -R -i ${pool}/${fs_vol}@${snapshot-previous} ${pool}/${fs_vol}@${snapshot}
# ... on destination:
zfs receive -F ${pool}/${fs_vol}
# Query file system / volume configuration (properties)
zfs get all ${pool}
zfs get all ${pool}/${fs_vol}
# Change file system / volume configuration (property)
zfs set <property>=<value> ${pool}/${fs_vol}
# More...
man zfs

View File

@ -1,5 +1,8 @@
# Create zip file # Create zip file
zip archive.zip file1 directory/ zip archive.zip file1 directory/
# Create zip file with password
zip -P password archive.zip file1
# To list, test and extract zip archives, see unzip # To list, test and extract zip archives, see unzip
cheat unzip cheat unzip

65
cheat/colorize.py Normal file
View File

@ -0,0 +1,65 @@
from __future__ import print_function
import sys
class Colorize:
def __init__(self, config):
self._config = config
def search(self, needle, haystack):
""" Colorizes search results matched within a line """
# if a highlight color is not configured, exit early
if not self._config.cheat_highlight:
return haystack
# otherwise, attempt to import the termcolor library
try:
from termcolor import colored
# if the import fails, return uncolored text
except ImportError:
return haystack
# if the import succeeds, colorize the needle in haystack
return haystack.replace(needle,
colored(needle, self._config.cheat_highlight))
def syntax(self, sheet_content):
""" Applies syntax highlighting """
# only colorize if cheat_colors is true, and stdout is a tty
if self._config.cheat_colors is False or not sys.stdout.isatty():
return sheet_content
# don't attempt to colorize an empty cheatsheet
if not sheet_content.strip():
return ""
# otherwise, attempt to import the pygments library
try:
from pygments import highlight
from pygments.lexers import get_lexer_by_name
from pygments.formatters import TerminalFormatter
# if the import fails, return uncolored text
except ImportError:
return sheet_content
# otherwise, attempt to colorize
first_line = sheet_content.splitlines()[0]
lexer = get_lexer_by_name('bash')
# apply syntax-highlighting if the first line is a code-fence
if first_line.startswith('```'):
sheet_content = '\n'.join(sheet_content.split('\n')[1:-2])
try:
lexer = get_lexer_by_name(first_line[3:])
except Exception:
pass
return highlight(
sheet_content,
lexer,
TerminalFormatter(bg=self._config.cheat_colorscheme))

120
cheat/configuration.py Normal file
View File

@ -0,0 +1,120 @@
from cheat.utils import Utils
import json
import os
class Configuration:
def __init__(self):
# compute the location of the config files
config_file_path_global = self._select([
os.environ.get('CHEAT_GLOBAL_CONF_PATH'),
'/etc/cheat',
])
config_file_path_local = self._select([
os.environ.get('CHEAT_LOCAL_CONF_PATH'),
os.path.expanduser('~/.config/cheat/cheat'),
])
# attempt to read the global config file
config = {}
try:
config.update(self._read_config_file(config_file_path_global))
except Exception as e:
Utils.warn('Error while parsing global configuration: '
+ e.message)
# attempt to read the local config file
try:
config.update(self._read_config_file(config_file_path_local))
except Exception as e:
Utils.warn('Error while parsing local configuration: ' + e.message)
# With config files read, now begin to apply envvar overrides and
# default values
# self.cheat_colors
self.cheat_colors = self._select([
Utils.boolify(os.environ.get('CHEAT_COLORS')),
Utils.boolify(os.environ.get('CHEATCOLORS')),
Utils.boolify(config.get('CHEAT_COLORS')),
True,
])
# self.cheat_colorscheme
self.cheat_colorscheme = self._select([
os.environ.get('CHEAT_COLORSCHEME'),
config.get('CHEAT_COLORSCHEME'),
'light',
]).strip().lower()
# self.cheat_user_dir
self.cheat_user_dir = self._select([
os.environ.get('CHEAT_USER_DIR'),
os.environ.get('CHEAT_DEFAULT_DIR'),
os.environ.get('DEFAULT_CHEAT_DIR'),
# TODO: XDG home?
os.path.expanduser(
os.path.expandvars(os.path.join('~', '.cheat'))
),
])
# self.cheat_editor
self.cheat_editor = self._select([
os.environ.get('CHEAT_EDITOR'),
os.environ.get('EDITOR'),
os.environ.get('VISUAL'),
config.get('CHEAT_EDITOR'),
'vi',
])
# self.cheat_highlight
self.cheat_highlight = self._select([
os.environ.get('CHEAT_HIGHLIGHT'),
config.get('CHEAT_HIGHLIGHT'),
False,
])
if isinstance(self.cheat_highlight, str):
Utils.boolify(self.cheat_highlight)
# self.cheat_path
self.cheat_path = self._select([
os.environ.get('CHEAT_PATH'),
os.environ.get('CHEATPATH'),
config.get('CHEAT_PATH'),
'/usr/share/cheat',
])
def _read_config_file(self, path):
""" Reads configuration file and returns list of set variables """
config = {}
if os.path.isfile(path):
with open(path) as config_file:
config.update(json.load(config_file))
return config
def _select(self, values):
for v in values:
if v is not None:
return v
def validate(self):
""" Validates configuration parameters """
# assert that cheat_highlight contains a valid value
highlights = [
'grey', 'red', 'green', 'yellow',
'blue', 'magenta', 'cyan', 'white',
False
]
if self.cheat_highlight not in highlights:
Utils.die("%s %s" %
('CHEAT_HIGHLIGHT must be one of:', highlights))
# assert that the color scheme is valid
colorschemes = ['light', 'dark']
if self.cheat_colorscheme not in colorschemes:
Utils.die("%s %s" %
('CHEAT_COLORSCHEME must be one of:', colorschemes))
return True

29
cheat/editor.py Normal file
View File

@ -0,0 +1,29 @@
from __future__ import print_function
from cheat.utils import Utils
import subprocess
class Editor:
def __init__(self, config):
self._config = config
def editor(self):
""" Determines the user's preferred editor """
# assert that the editor is set
if not self._config.cheat_editor:
Utils.die(
'You must set a CHEAT_EDITOR, VISUAL, or EDITOR environment '
'variable or setting in order to create/edit a cheatsheet.'
)
return self._config.cheat_editor
def open(self, filepath):
""" Open `filepath` using the EDITOR specified by the env variables """
editor_cmd = self.editor().split()
try:
subprocess.call(editor_cmd + [filepath])
except OSError:
Utils.die('Could not launch ' + self.editor())

View File

@ -1,76 +1,64 @@
from cheat.editor import Editor
from cheat.utils import Utils
import io
import os import os
import shutil import shutil
from cheat import sheets
from cheat.utils import die, open_with_editor
def copy(current_sheet_path, new_sheet_path): class Sheet:
""" Copies a sheet to a new path """
# attempt to copy the sheet to DEFAULT_CHEAT_DIR def __init__(self, config, sheets):
try: self._config = config
shutil.copy(current_sheet_path, new_sheet_path) self._editor = Editor(config)
self._sheets = sheets
# fail gracefully if the cheatsheet cannot be copied. This can happen if def _exists(self, sheet):
# DEFAULT_CHEAT_DIR does not exist """ Predicate that returns true if the sheet exists """
except IOError: return (sheet in self._sheets.get() and
die('Could not copy cheatsheet for editing.') os.access(self._path(sheet), os.R_OK))
def _exists_in_default_path(self, sheet):
""" Predicate that returns true if the sheet exists in default_path"""
default_path = os.path.join(self._config.cheat_user_dir, sheet)
return (sheet in self._sheets.get() and
os.access(default_path, os.R_OK))
def create_or_edit(sheet): def _path(self, sheet):
""" Returns a sheet's filesystem path """
return self._sheets.get()[sheet]
def edit(self, sheet):
""" Creates or edits a cheatsheet """ """ Creates or edits a cheatsheet """
# if the cheatsheet does not exist # if the cheatsheet does not exist
if not exists(sheet): if not self._exists(sheet):
create(sheet) new_path = os.path.join(self._config.cheat_user_dir, sheet)
self._editor.open(new_path)
# if the cheatsheet exists but not in the default_path, copy it to the # if the cheatsheet exists but not in the default_path, copy it to the
# default path before editing # default path before editing
elif exists(sheet) and not exists_in_default_path(sheet): elif self._exists(sheet) and not self._exists_in_default_path(sheet):
copy(path(sheet), os.path.join(sheets.default_path(), sheet)) try:
edit(sheet) shutil.copy(
self._path(sheet),
os.path.join(self._config.cheat_user_dir, sheet)
)
# fail gracefully if the cheatsheet cannot be copied. This can
# happen if CHEAT_USER_DIR does not exist
except IOError:
Utils.die('Could not copy cheatsheet for editing.')
self._editor.open(self._path(sheet))
# if it exists and is in the default path, then just open it # if it exists and is in the default path, then just open it
else: else:
edit(sheet) self._editor.open(self._path(sheet))
def read(self, sheet):
def create(sheet):
""" Creates a cheatsheet """
new_sheet_path = os.path.join(sheets.default_path(), sheet)
open_with_editor(new_sheet_path)
def edit(sheet):
""" Opens a cheatsheet for editing """
open_with_editor(path(sheet))
def exists(sheet):
""" Predicate that returns true if the sheet exists """
return sheet in sheets.get() and os.access(path(sheet), os.R_OK)
def exists_in_default_path(sheet):
""" Predicate that returns true if the sheet exists in default_path"""
default_path_sheet = os.path.join(sheets.default_path(), sheet)
return sheet in sheets.get() and os.access(default_path_sheet, os.R_OK)
def is_writable(sheet):
""" Predicate that returns true if the sheet is writeable """
return sheet in sheets.get() and os.access(path(sheet), os.W_OK)
def path(sheet):
""" Returns a sheet's filesystem path """
return sheets.get()[sheet]
def read(sheet):
""" Returns the contents of the cheatsheet as a String """ """ Returns the contents of the cheatsheet as a String """
if not exists(sheet): if not self._exists(sheet):
die('No cheatsheet found for ' + sheet) Utils.die('No cheatsheet found for ' + sheet)
with open(path(sheet)) as cheatfile: with io.open(self._path(sheet), encoding='utf-8') as cheatfile:
return cheatfile.read() return cheatfile.read()

View File

@ -1,42 +1,34 @@
from cheat.colorize import Colorize
from cheat.utils import Utils
import io
import os import os
from cheat import cheatsheets
from cheat.utils import die
def default_path(): class Sheets:
""" Returns the default cheatsheet path """
# determine the default cheatsheet dir def __init__(self, config):
default_sheets_dir = os.environ.get('DEFAULT_CHEAT_DIR') or os.path.join('~', '.cheat') self._config = config
default_sheets_dir = os.path.expanduser(os.path.expandvars(default_sheets_dir)) self._colorize = Colorize(config)
# create the DEFAULT_CHEAT_DIR if it does not exist # Assembles a dictionary of cheatsheets as name => file-path
if not os.path.isdir(default_sheets_dir): self._sheets = {}
try: sheet_paths = [
# @kludge: unclear on why this is necessary config.cheat_user_dir
os.umask(0000) ]
os.mkdir(default_sheets_dir)
except OSError: # merge the CHEAT_PATH paths into the sheet_paths
die('Could not create DEFAULT_CHEAT_DIR') if config.cheat_path:
for path in config.cheat_path.split(os.pathsep):
if os.path.isdir(path):
sheet_paths.append(path)
# assert that the DEFAULT_CHEAT_DIR is readable and writable if not sheet_paths:
if not os.access(default_sheets_dir, os.R_OK): Utils.die('The CHEAT_USER_DIR dir does not exist '
die('The DEFAULT_CHEAT_DIR (' + default_sheets_dir +') is not readable.') + 'or the CHEAT_PATH is not set.')
if not os.access(default_sheets_dir, os.W_OK):
die('The DEFAULT_CHEAT_DIR (' + default_sheets_dir +') is not writable.')
# return the default dir
return default_sheets_dir
def get():
""" Assembles a dictionary of cheatsheets as name => file-path """
cheats = {}
# otherwise, scan the filesystem # otherwise, scan the filesystem
for cheat_dir in reversed(paths()): for cheat_dir in reversed(sheet_paths):
cheats.update( self._sheets.update(
dict([ dict([
(cheat, os.path.join(cheat_dir, cheat)) (cheat, os.path.join(cheat_dir, cheat))
for cheat in os.listdir(cheat_dir) for cheat in os.listdir(cheat_dir)
@ -45,46 +37,39 @@ def get():
]) ])
) )
return cheats def directories(self):
def paths():
""" Assembles a list of directories containing cheatsheets """ """ Assembles a list of directories containing cheatsheets """
sheet_paths = [ sheet_paths = [
default_path(), self._config.cheat_user_dir,
cheatsheets.sheets_dir()[0],
] ]
# merge the CHEATPATH paths into the sheet_paths # merge the CHEATPATH paths into the sheet_paths
if 'CHEATPATH' in os.environ and os.environ['CHEATPATH']: for path in self._config.cheat_path.split(os.pathsep):
for path in os.environ['CHEATPATH'].split(os.pathsep):
if os.path.isdir(path):
sheet_paths.append(path) sheet_paths.append(path)
if not sheet_paths:
die('The DEFAULT_CHEAT_DIR dir does not exist or the CHEATPATH is not set.')
return sheet_paths return sheet_paths
def get(self):
""" Returns a dictionary of cheatsheets as name => file-path """
return self._sheets
def list(): def list(self):
""" Lists the available cheatsheets """ """ Lists the available cheatsheets """
sheet_list = '' sheet_list = ''
pad_length = max([len(x) for x in get().keys()]) + 4 pad_length = max([len(x) for x in self.get().keys()]) + 4
for sheet in sorted(get().items()): for sheet in sorted(self.get().items()):
sheet_list += sheet[0].ljust(pad_length) + sheet[1] + "\n" sheet_list += sheet[0].ljust(pad_length) + sheet[1] + "\n"
return sheet_list return sheet_list
def search(self, term):
def search(term):
""" Searches all cheatsheets for the specified term """ """ Searches all cheatsheets for the specified term """
result = '' result = ''
for cheatsheet in sorted(get().items()): for cheatsheet in sorted(self.get().items()):
match = '' match = ''
for line in open(cheatsheet[1]): for line in io.open(cheatsheet[1], encoding='utf-8'):
if term in line: if term in line:
match += ' ' + line match += ' ' + self._colorize.search(term, line)
if match != '': if match != '':
result += cheatsheet[0] + ":\n" + match + "\n" result += cheatsheet[0] + ":\n" + match + "\n"

View File

@ -1,71 +1,26 @@
from __future__ import print_function from __future__ import print_function
import os
import sys import sys
import subprocess
def colorize(sheet_content): class Utils:
""" Colorizes cheatsheet content if so configured """
# only colorize if so configured
if not 'CHEATCOLORS' in os.environ:
return sheet_content
try:
from pygments import highlight
from pygments.lexers import get_lexer_by_name
from pygments.formatters import TerminalFormatter
# if pygments can't load, just return the uncolorized text
except ImportError:
return sheet_content
first_line = sheet_content.splitlines()[0]
lexer = get_lexer_by_name('bash')
if first_line.startswith('```'):
sheet_content = '\n'.join(sheet_content.split('\n')[1:-2])
try:
lexer = get_lexer_by_name(first_line[3:])
except Exception:
pass
return highlight(sheet_content, lexer, TerminalFormatter())
@staticmethod
def die(message): def die(message):
""" Prints a message to stderr and then terminates """ """ Prints a message to stderr and then terminates """
warn(message) Utils.warn(message)
exit(1) exit(1)
@staticmethod
def editor():
""" Determines the user's preferred editor """
# determine which editor to use
editor = os.environ.get('CHEAT_EDITOR') \
or os.environ.get('VISUAL') \
or os.environ.get('EDITOR') \
or False
# assert that the editor is set
if editor == False:
die(
'You must set a CHEAT_EDITOR, VISUAL, or EDITOR environment '
'variable in order to create/edit a cheatsheet.'
)
return editor
def open_with_editor(filepath):
""" Open `filepath` using the EDITOR specified by the environment variables """
editor_cmd = editor().split()
try:
subprocess.call(editor_cmd + [filepath])
except OSError:
die('Could not launch ' + editor())
def warn(message): def warn(message):
""" Prints a message to stderr """ """ Prints a message to stderr """
print((message), file=sys.stderr) print((message), file=sys.stderr)
@staticmethod
def boolify(value):
""" Type-converts 'true' and 'false' to Booleans """
# if `value` is not a string, return it as-is
if not isinstance(value, str):
return value
# otherwise, convert "true" and "false" to Boolean counterparts
return value.strip().lower() == "true"

10
ci/lint.sh Executable file
View File

@ -0,0 +1,10 @@
#!/bin/sh
# Resolve the app root
SCRIPT=`realpath $0`
SCRIPTPATH=`dirname $SCRIPT`
APPROOT=`realpath "$SCRIPTPATH/.."`
flake8 $APPROOT/setup.py
flake8 $APPROOT/bin/cheat
flake8 $APPROOT/cheat/*.py

6
config/cheat Normal file
View File

@ -0,0 +1,6 @@
{
"CHEAT_COLORS" : true,
"CHEAT_COLORSCHEME" : "light",
"CHEAT_EDITOR" : "vi",
"CHEAT_PATH" : "/usr/share/cheat"
}

View File

@ -1,9 +1,20 @@
from distutils.core import setup from distutils.core import setup
import os import os
# determine the directory in which to install system-wide cheatsheets
# KLUDGE: It would be better to read `/usr/share/cheat` from `config/cheat`
# rather than hard-coding it here
cheat_path = os.environ.get('CHEAT_PATH') or '/usr/share/cheat'
# aggregate the systme-wide cheatsheets
cheat_files = []
for f in os.listdir('cheat/cheatsheets/'):
cheat_files.append(os.path.join('cheat/cheatsheets/', f))
# specify build params
setup( setup(
name='cheat', name='cheat',
version = '2.2.1', version='2.5.0',
author='Chris Lane', author='Chris Lane',
author_email='chris@chris-allen-lane.com', author_email='chris@chris-allen-lane.com',
license='GPL3', license='GPL3',
@ -14,15 +25,16 @@ setup(
url='https://github.com/chrisallenlane/cheat', url='https://github.com/chrisallenlane/cheat',
packages=[ packages=[
'cheat', 'cheat',
'cheat.cheatsheets',
'cheat.test', 'cheat.test',
], ],
package_data = {
'cheat.cheatsheets': [f for f in os.listdir('cheat/cheatsheets') if '.' not in f]
},
scripts=['bin/cheat'], scripts=['bin/cheat'],
install_requires=[ install_requires=[
'docopt >= 0.6.1', 'docopt >= 0.6.1',
'pygments >= 1.6.0', 'pygments >= 1.6.0',
] 'termcolor >= 1.1.0',
],
data_files=[
(cheat_path, cheat_files),
('/etc', ['config/cheat']),
],
) )

View File

@ -0,0 +1,86 @@
import unittest2
import os
import shutil
from cheat.configuration import Configuration
def _set_loc_conf(key, value):
_path = os.path.dirname(os.path.abspath(__file__)) + '/home/.config/cheat/cheat'
if value == None:
os.remove(_path)
else:
if not os.path.exists(os.path.dirname(_path)):
os.makedirs(os.path.dirname(_path))
f = open(_path,"w+")
f.write('{"'+ key +'":"'+ value +'"}')
f.close()
def _set_glob_conf(key, value):
_path = os.path.dirname(os.path.abspath(__file__))+ "/etc/cheat"
if value == None:
os.remove(_path)
else:
if not os.path.exists(os.path.dirname(_path)):
os.mkdir(os.path.dirname(_path))
f = open(_path,"w+")
f.write('{"'+ key +'":"'+ value +'"}' )
f.close()
def _set_env_var(key, value):
if value == None:
del os.environ[key]
else:
os.environ[key] = value
def _configuration_key_test(TestConfiguration, key,values, conf_get_method):
for glob_conf in values:
_set_glob_conf(key,glob_conf)
for loc_conf in values:
_set_loc_conf(key,loc_conf)
for env_conf in values:
_set_env_var(key,env_conf)
if env_conf:
TestConfiguration.assertEqual(conf_get_method(Configuration()),env_conf)
elif loc_conf:
TestConfiguration.assertEqual(conf_get_method(Configuration()),loc_conf)
elif glob_conf:
TestConfiguration.assertEqual(conf_get_method(Configuration()),glob_conf)
else:
TestConfiguration.assertEqual(conf_get_method(Configuration()),None)
class ConfigurationTestCase(unittest2.TestCase):
def setUp(self):
os.environ['CHEAT_GLOBAL_CONF_PATH'] = os.path.dirname(os.path.abspath(__file__)) \
+ '/etc/cheat'
os.environ['CHEAT_LOCAL_CONF_PATH'] = os.path.dirname(os.path.abspath(__file__)) \
+ '/home/.config/cheat/cheat'
def test_get_editor(self):
_configuration_key_test(self,"EDITOR",["nano","vim","gedit",None],
Configuration.get_editor)
def test_get_cheatcolors(self):
_configuration_key_test(self,"CHEATCOLORS",["true",None],
Configuration.get_cheatcolors)
def test_get_cheatpath(self):
_configuration_key_test(self,"CHEATPATH",["/etc/myglobalcheats",
"/etc/anotherglobalcheats","/rootcheats",None],Configuration.get_cheatpath)
def test_get_defaultcheatdir(self):
_configuration_key_test(self,"DEFAULT_CHEAT_DIR",["/etc/myglobalcheats",
"/etc/anotherglobalcheats","/rootcheats",None],Configuration.get_default_cheat_dir)
def tearDown(self):
shutil.rmtree(os.path.dirname(os.path.abspath(__file__)) +'/etc')
shutil.rmtree(os.path.dirname(os.path.abspath(__file__)) +'/home')