This is like Stack Exchange, but past-Joe answers the questions of present-Joe. (Necessarily, this only works if present-Joe answers the questions of future-Joe, by recording how he solves new/obnoxious problems.)
man bash
and man zshall
are examples of how to learn about your shell (Bash and Zsh, respectively).
All of these work:
echo $0
echo $SHELL
ps | grep $$
ps -$$
Note, $$
expands to the process ID of the current shell.
- man -- brief manual pages
- info -- long-winded and explanations, but often just the man page
- apropos -- man pages with matchning keywords
- which -- tells you where a command is located
- type -- tells you how a command will be interpreted (
/^\s*type
inman bash
)
chsh -s /usr/bin/zsh
Many commands, such as read
, source
, fg
, bg
, and cd
, are built into Bash and don't have their own man pages.
The Bash manual (man bash
) talks about these under the heading SHELL BUILTIN COMMANDS on line 2580.
/^\s*type
in man bash
would find the type
built-in relatively quickly by searching for a line that starts with some whitespace followed by "type" (assuming less
is your pager).
$? # exit status of the previous command
$! # PID of the previous backgrounded command
$0 # the name of the command that invoked the current process
$1 # the first argument of the process
$2 # the second argument of the process
$@ # all arguments of the process
IMO, this is mostly useful for processing files found by find
or ls
.
For this purpose, the -r
flag is almost always preferred, so files with spaces in their names won't get broken into multiple words.
(This obvioulsy requires that you feed read
file names with the spaces escaped.)
If you want to mess with how the words are broken up, you need to [temporarily!] modify the variable IFS
, which controlls how words are broken. (This is similar to how you might hack for f in *
to cycle through file names.)
tree
is a super-useful command that shows you the structure and contents of a directory.
This will give you an HTML file that links to everything, so you can view it in a browser:
`tree -H file://\`pwd\` > tree.html`
echo asdf 2>&1
redirect stream 2 (stderr) to stream 1 (stdout) (so, you get both)
echo asdf 1>&/dev/null
redirect stdout into /dev/null (so, basically ignore it)
echo asdf >> both.log 2>&1
redirect both outputs to a log file
ls notafile 2>&1 | tee -a asdf.log
redirect both outputs to a log file and the terminal
The readline
library controls the behavior of a lot of programs that use a command line interface (CLI).
This includes shells like Bash and Zsh, as well as stuff like R and Python.
The ~/.inputrc file controls the behavior of this library.
So, spending some time on that can make all your shells more productive, enjoyable, and uniform.
The system default is usually somewhere like /etc/inputrc
.
str()
gets the structure of something (e.g., if you have a list of lists.)
typeof()
tells you the storage type of something.
class()
tells you... the class of something.
help()
and ??
give you the help pages for functions.
help()
will sometimes give you useful information, if the package authors have bothered to tell you how their objects work.
dir()
will tell you the attributes of a thing, though there are usually too many for this to be helpful.
print()
can be helpful, but many similar types print in identical ways.
type()
tells you the type of an object (specifically, what modules/objects it comes from). This can be surprisingly useless...
The usual calls you want are import matplotlib.pyplot as plt
and plt.plot(x,y)
.
If you're going topless (without a display server), you'll need to do
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
Otherwise, matplotlib
will try to access your non-existant cursor and trip all over itself.
Typically, the pythonic way to do things is to use generators instead of sequences. So, stuff like range()
which only gets instantiated inside things like for
and with
.
(Pay attention to off-by-one errors here!!! The convention for this built-in is inconsistent. range(1,10)
generates the integers from 1 to 9, the last of which is accessed by index 8. Seriously.)
For lists of floats, numpy.linspace(start, stop, num)
is the best option. Apallingly, there is no mainstream equivalent (AFAIK) to R's seq()
, so you'll have to manage the step size between elements on your own (and deal with the corresponding fence post rounding BS).
Example: look for anything occurring between filename="
and "
. Note that this is using the Perl syntax, -P
.
cat dumpHeader.out | grep -P -e '(?<=filename=").*(?=")'
Look for "respond" but not "correspond".
grep -riP '(?<!cor)respond'
Vim, for example, does not use the Perl syntax. See the pattern-multi-items
help for more info.
This is also called non-greedy matching. Say I have an HTML file, and I want to match individual bold sections.
<b>Match this,</b> but not this this. <b>Also match this.</b>
grep -o -P '<b>.*?</b>' example.html
would match only the bold tags and their contents,
unlike grep -o '<b>.*</b>' example.html
which also matches stuff between bold elements.
Note that this is a Perl-ism, as indicated by the -P
flag.
So, this won't work in some regex systems.
An example of a negation in Vim would be ^#\@!
, which matches any line that doesn't start with an octothorpe.
ls *.pdf | awk -e '{print "pdfgrep -n [:alphanum:] "$1"| tail -1"}' | sh
Pipe the names of the PDFs to awk. Use awk to build those into a command which: * uses pdfgrep to search that PDF for lines with any alphanumeric character, prepending the line number * pipe the results to tail, which cuts out all but the last result Send that command to the shell.
This doesn't tell you the file names, and also outputs the text on the last line of each PDF :(
My hope is that this is an easy way to thwart usb attacks.
Using dconf-editor, under org.gnome.desktop.media-handling
, uncheck automount
and optionally automount-open
.
To do this without a GUI, you'd do
gsettings set org.gnome.desktop.media-handling automount false
.
Both of these are frontents for dconf
.
$ sudo apt-get install arduino arduino-core
- Plug in the arduino
- In the IDE, go to
Tools
->Port
select the arduino. (Either figure it out by plugging it in/out or by having it be the only thing plugged in.)
You'll probably need to add yourself to the usergroup that's allowed to talk to ports:
$ sudo usermod -a -G dialout joedang
On some machines, you may need to restart after adding yourself.
"Keycodes" refer to the numerical designations of physical keys. "Keysyms" refer to the abstract syntactic meaning of those keys. Keysyms have a four-byte hexadecimal representation, but are also referred to by human-readable strings. Keyboard layouts define how keycodes are translated into keysyms.
For example, keycode 9 refers to the top left key on my keyboard, which happens to have "Esc" printed on it. Meanwhile, keycode 66 refers to the far-left key on the home row, which happens to have "CapsLock" printed on it. If I'm using the "correct" keyboard layout, keycode 66 (the "CapsLock" key) will send the "Caps_Lock"
setxkbmap
is the "porcelain" for keyboard layouts.
It allows you to select layouts, perform common remappings, and other stuff.
You can find a list of the pre-configured remapping optins in
/usr/share/X11/xkb/rules/base.lst
.
Note that these options are not systematic. Just because you can write something
that sounds like a thing, doesn't mean it will work.
For example, setxkbmap -option caps:escape
is an option to take whatever keycode is currently
mapped to the Caps_Lock keysym and map it to the Escape keysym.
However, a:b
will not do they same with the "a" and "b" keysyms,
because that is not a preconfigured option.
For something like that, you'd need to use xmodmap
.
xmodmap
is a bit more low-level.
It allows you to explicitly map individual keycodes to keysyms.
setxkbmap -layout us -option
will reset the keyboard layout to "us" and
clear all the options.
xev
will print out X events.
This can be used to figure out what the keycodes of physical keys are
and what keysyms they're sending.
xinput
will configure and explore the attached input devices.
xinput list
shows you what's connected and what it's device ID is.
xinput list-props DEVICE_ID
shows you the available properties of a device,
what the IDs for those properties are, and what the values of those properties
are.
xinput set-prop DEVICE_ID PROPERTY_ID
lets you change those properties.
This can be used to change things like trackpad behavior and pointer acceleration.
The sensors
command from the lm_sensors
library will print out some pretty info.
/sys/class/power_supply/BAT0/
typically has info on the main battery.
The power_supply/
directory typically has useful info on other devices.
upower
can give prettier output, but you need to give it a special device name.
The upower
man page isn't fully written, so use upower -h
.
upower -e
will tell you what device names are available.
/sys/class/thermal/thermal_zone0/temp
typically has the temperature of the CPU in milli Celsius.
Use $ md5sum myPackage.tar.gz
to show the MD5 hash for a file.
Use $ md5sum -c fileList.txt
to check if multiple files are 'OK', with fileList.txt
being something like
283158c7da8c0ada74502794fa8745eb ubuntu-6.10-alternate-amd64.iso
549ef19097b10ac9237c08f6dc6084c6 ubuntu-6.10-alternate-i386.iso
5717dd795bfd74edc2e9e81d37394349 ubuntu-6.10-alternate-powerpc.iso
99c3a849f6e9a0d143f057433c7f4d84 ubuntu-6.10-desktop-amd64.iso
b950a4d7cf3151e5f213843e2ad77fe3 ubuntu-6.10-desktop-i386.iso
a3494ff33a3e5db83669df5268850a01 ubuntu-6.10-desktop-powerpc.iso
2f44a48a9f5b4f1dff36b63fc2115f40 ubuntu-6.10-server-amd64.iso
cd6c09ff8f9c72a19d0c3dced4b31b3a ubuntu-6.10-server-i386.iso
6f165f915c356264ecf56232c2abb7b5 ubuntu-6.10-server-powerpc.iso
4971edddbfc667e0effbc0f6b4f7e7e0 ubuntu-6.10-server-sparc.iso
which the distributor will usually provide in that format.
You can do $ find -type f -exec sha512sum '{}' + > check.txt
to create such a list.
When you download the source for stuff, this helps you verify that it's not corrupted (or, you know, tampered with). You can also use it to verify that large copy jobs haven't been corrupted.
If you hash the concatenation of a password and a website name, you can use that as a crude way of adding security to a reused password. (When you need to log in, rehash the password + site name and copy the result into the password field.)
cronie
is the implementation I went with on arxgus
.
It needed to be enabled/started with Systemd.
A user's "crontab" contains "cron jobs". Each user gets a crontab. Each jobs is a command that gets run at the specified times.
Cron jobs are edited with crontab -e
and read with crontab -l
.
They are not meant to be edited directly.
Cron jobs use the following format.
Each uncommented, non-empty line of a crontab is a job.
M H d m u /path/to/command arg1 arg2
The things before the command specify when they command is meant to be run.
They are:
field | scale | range |
---|---|---|
M | minutes | 0-59 |
H | hours | 0-23 |
d | days | 0-31 |
m | months | 0-12 |
u | days-of-the-week | 0-7 (Sunday is 0 and 7) |
In addition to the numeric values, you can use these symbols to express more complicated schedules:
symbol | meaning |
---|---|
* | all possible values |
, | separates values in a list |
- | specifies a range |
/ | specifies a step |
The following shorthands can be use to replace the entire 5-field schedule:
shorthand | meaning |
---|---|
@hourly | Run once every hour i.e. 0 * * * * |
@midnight | Run once every day i.e. 0 0 * * * |
@daily | same as midnight |
@weekly | Run once every week, i.e. 0 0 * * 0 |
@monthly | Run once every month i.e. 0 0 1 * * |
@annually | Run once every year i.e. 0 0 1 1 * |
@yearly | same as @annually |
@reboot | Run once at every startup |
The first job will append "cron works" to /tmp/crontest
every minute.
The second line will append the same to /tmp/crontest_hourly
every hour.
* * * * * /usr/bin/echo "cron works" >> /tmp/crontest
@hourly /usr/bin/echo "cron works" >> /tmp/crontest_hourly
Each line of /etc/cron.allow
contains the username of someone who is allowed to use crontab -e
.
If this file exists, but your username isn't in it, crontab -e
shouldn't work.
Each line of /etc/cron.deny
contains the username of someone who is disallowed to use crontab -e
.
If this file exists, and your username is in it, crontab -e
shouldn't work.
The cron jobs for a user are run as that user.
If you need a cron job to be run as another user, like root, you can use the su
command or the -u
flag for crontab.
Note that this will edit the crontab for that user, not your crontab.
Set all the mp3 files to have the timestamp of ../flac/Tiger.flac
:
$ touch -d "$(date -R -r ../flac/Tiger.flac)" *.mp3
Strip the track number from a bunch of songs:
$ rename 's/^[0-9][0-9] - *//' *
01 - The Starting Line.mp3
02 - Floor Corn.mp3
03 - ACVC.mp3
04 - 300MB.mp3
05 - Revolution #5.mp3
06 - Dear Dinosaur.mp3
07 - Annoyed Grunt.mp3
08 - Bustin.mp3
09 - Blockbuster.mp3
10 - Busta.mp3
11 - Tiger.mp3
12 - The End.mp3
13 - Shady Interlude.mp3
14 - T.I.M.E..mp3
15 - Smooth.mp3
16 - Stand By Meme.mp3
17 - Wallspin.mp3
18 - Wow Wow.mp3
19 - Mouth Pressure.mp3
20 - Shit.mp3
becomes
300MB.mp3
ACVC.mp3
Annoyed Grunt.mp3
Blockbuster.mp3
Busta.mp3
Bustin.mp3
Dear Dinosaur.mp3
Floor Corn.mp3
Mouth Pressure.mp3
Revolution #5.mp3
Shady Interlude.mp3
Shit.mp3
Smooth.mp3
Stand By Meme.mp3
The End.mp3
The Starting Line.mp3
Tiger.mp3
T.I.M.E..mp3
Wallspin.mp3
Wow Wow.mp3
~~
avconv
* and flac2mp3
are pretty good. The default settings for flac2mp3
are basically perfect. You'll probably have to compile flac2mp3 from source.
* Lately, avconv
has not been so great. It couldn't find the codecs required for writing to mp3
, despite attempts to help it find them.
lame
is a stand-alone library/command that only writes to mp3
.
~~
ffmpeg
has come out on top as the silver bullet of audio-visual media conversion.
easytag
is a GUI-only program that handles mp3
tags (called ID3
).
youtube-dl
is also good for acquiring stuff, but don't count on your package manager's repos being up to date *cough*Ubuntu*cough*. You pretty much have to compile both youtube-dl
and avconv
ffmpeg
from source. (libav
is the parent package/project for the avconv
command.)
The main places to get help are:
- the ffmpeg man pages (ffmpeg, ffmpeg-filters, ffmpeg-utils, et cetera),
ffmpeg -h
(which can take arguments),- and the online documentation (which really just mirrors the man pages).
You can find out what filters are available by using
ffmpeg -filters
. You can get some help with a filter withffmpeg -h filter=crop
.
The -an
flag for ffmpeg
can be used to remove all audio streams from an output file.
There are similar flags for video, subtitles, and data.
ffmpeg -i input.mp4 -c copy -an silent.mp4
convert -delay 20 -loop 0 *.png myanimation.gif
Compiles all the PNG
s in the WD to a GIF
.
A nice way to preview this kind of stuff is with the animate
command.
I also made a vid2small
utility in Python3 that can convert stuff to GIF
.
Some cameras will output video in chunks, to avoid excessively large files. This can potentially be a pain for editing, if there are many files over which a single shot is broken.
Some file types, such as mp4 can actually be concatenated directly using cat
. However, this does not recalculate the time stamps, so viewers like vlc
will not see anything but the first video.
You can use the concat
demuxer in ffmpeg to concatenate such files and recalculate the time stamps (without deencoding and reencoding the videos) like so:
$ cat vidList.txt
file 44.mp4
file 45.mp4
file 46.mp4
$ ffmpeg -f concat -i vidList.txt -c copy bigVid.mp4
You can just specify the output file in ffmpeg to be an image with a printf-style number.
In this example, the drawtext
video filter also adds a timestamp.
ffmpeg -i sourceVid.mp4 -ss $(startTime) -to $(stopTime) \
-vf "drawtext=text=time\= %{pts} s: \
fontcolor=green: x=5: y=5: fontsize=35" \
frames%03d.png
This is an example of a complex filter in ffmpeg. This strings together a bunch of other filters in a potentially non-linear way.
# ⬐video streams 0 and 1, respectively
ffmpeg \
-i garyAnimation_alligned.gif \
-i psasMotto_YOLO.png \
-filter_complex "[0:v]scale=w=1056:h=-1, crop=w=1056:h=816:y=-100[b1], [b1][1:v]overlay" output.mp4
# | ⬑-----------------⬑---------filter names------------------⬏ | |
# | | | | | | | | | |
# ⬑automatic name for video 1 | | | | |
# ⬑width ⬑height= nearest mod 1 | | | | |
# ⬑ ⬑implied output and input streams | | |
# ⬑label output stream as b1
# ⬑use output labeled b1 as first input
# ⬑use video 1 as second input
# ⬑ ⬑implied output
Use the loudnorm
audio filter.
ffmpeg -i mictest.ogg -af loudnorm mictest_norm.ogg
To stop recording with ffmpeg, you can just press Control-C.
ffmpeg -f pulse -i default mictest.ogg
ffmpeg -f x11grab -i :0.0 screencast.mp4
check for device names: v4l2-ctl --list-devices
check which one's which: mpv /dev/video0
record: ffmpeg -f v4l2 -i /dev/video0 camtest.mp4
GIMP checks for typefaces on its own, so running $ sudo fc-cache -fv
may be unnecessary.
Copy the font to /usr/share/fonts/truetype/
(or the appropriate directory if it's not TTF) and run $ sudo fc-cache -fv
.
Copy to ~/.fonts/
and run $ sudo fc-cache -fv
.
The -exec
option in find
is useful for this. For example, you can create checksums for all the mp3
files in the CWD by doing
find . -name '*.mp3' -exec md5sum '{}' \; | tee -a mp3checksum.mp3
steghide
works well, but is limited to a few file formats.
steghide embed -ef secret.txt -cf fluffybunny.jpg -sf fluffybunny_steg.jpg -p "12345password"
steghide extract -sf fluffybunny_steg.jpg -xf extracted_secret.txt "12345password"
Pull from a remote directory:
rsync -r user@host:~/yourdir/ ~/mydir/
Push to a remote directory:
rsync -r mydir/ user@host:~/yourdir/
user
is your login name on that machine. (You will need to know the password for ~/.ssh/id_rsa
to get in.) host
can be an IP address or a domain (192.168.1.1
, pdx.edu
, et cetera).
You can also explicitly use ssh as the wrapper for rsync, if a machine doesn't like to talk to rsync by default.
For example, using ssh over port 2222 to copy test.txt from a machine at a local IP:
rsync -e 'ssh -p 2222' [email protected]:test.txt ./
Let say, hypothetically, that someone was a butt with their repos.
They have a repo named lv3.0-recovery
and, rather than renaming the repo to
lv3-recovery
and continuing to work or making a new repo called
lv3.1-recovery
, they've made a directory named LV3.1
within it and done all
their work in there.
git clone lv3.0-recovery lv3.1-recovery #1
cd lv3.1-recovery #2
git filter-branch --subdirectory-filter LV3.1 -- --all #3
On line 1, we create a new repo. This could probably be done in a branch, but
paranoia. On line 2, we go into that repo.
On line 3, we rewrite the history to only include the LV3.1
directory.
This new history will have the same commit messages, dates, names, et cetera.
However, the commit hashes and parents will change.
"Secure SHell" (SSH) is a tool to securely communicate with another machine.
In order to connect via SSH, the host machine (the one where you aren't executing the ssh command)
needs to have an SSH server running and a port open (22 by default).
openssh-server
and sshd
are reasonable options for this.
When you connect to a host, you need to have each other's public keys.
(Or, you need to verify their fingerprint.)
You need to open a port in the host's firewall, in order to accept connections.
the easiest way to do this is with the Uncomplicated FireWall package, ufw
.
ufw allow 22
will open port 22, the default for ssh.
ssh-keygen
creates keys.
Checkout ssh-copy-id
for a convenient way to copy public keys around.
These pages are great:
https://www.digitalocean.com/community/tutorials/how-to-configure-ssh-key-based-authentication-on-a-linux-server
https://www.cyberciti.biz/faq/create-ssh-config-file-on-linux-unix/
When you connect to a new host, you'll be confronted with a message like this:
$ scp -r [email protected]:.gpg .gpg
The authenticity of host '192.168.254.13 (192.168.254.13)' can't be established.
ECDSA key fingerprint is SHA256:9gohu/O6O4eIBA4cRZ8WBganGxptHsAjE7l/ZeemrWs.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
In order to verify that you're not connecting to an imposter, you'll need to verify the host machine's key.
This can be done with ssh-keygen -lf /etc/ssh/ssh_host_ecdsa_key.pub
.
If you're using older/newer machines, you may need to use a different hashing algorithm.
(I think my Ubuntu 14 machine used md5.)
This can be controlled with the -E
option.
When connecting to a new IP, you may get a warning about it being added to the known_hosts
file.
To check the fingerprint of the host, you can do ssh-keygen -lf ~/.ssh/known_hosts
.
GitHub publishes the fingerprints and IP addresses of their SSH servers at https://api.github.com/meta
.
- a nice guide to wireguard VPN shenanigans
- For something like Mullvad:
- Download the ZIP of the configuration files.
- Run
nmcli connection import type wireguard file mullvad-SERVERLABEL.conf
for each configuration file. - Make sure you only have one VPN selected in the NetworkManager applet!
My general strategy is to download an unzip the source into /tmp/
. Remember to do a checksum on the downloaded archive!
$ pwd
/tmp
$ cat checksum.txt
6503368c6b069bcbb00461e00a40db9d MYLIB_1.2.3.tar.gz
$ md5sum -c checksum.txt
MYLIB_1.2.3.tar.gz: OK
$ tar -zxvf MYLIB_1.2.3.tar.gz
Of course, you should read anything named README
or INSTALL
for more detailed instructions.
Generally, it should work fine to go into MYLIB_1.2.3
just run:
$ ./configure
$ make
$ sudo make install
For tidyness purposes, you may want to create /tmp/MYLIB_build
and run those commands from there. (You would need to do make ../MYLIB_1.2.3
et cetera.)
If you're installing into your home directory, you don't need to use sudo
. I stronly prefer installing free/open software to /usr/local/
and commercial software to /opt/
.
Sometimes the software won't put its executables into /usr/local/bin/
, and so they won't be in your path. To add them, add a line of this form to your ~/.bashrc
:
PATH=/usr/local/MYLIB/bin:$PATH
export PATH
I prefer to put all my path fiddling together, near the end of .bashrc
, and have just one export
statement.
Note: if the software puts its man and info pages in a sane location, like /usr/local/MYLIB/man
, then the man
command will automatically pick them up.
Otherwise, you'll need to do some similar path concatenations with MANPATH
and INFOPATH
. e.g.:
MANPATH=/usr/local/MYLIB/foobar/man:$MANPATH
export MANPATH
INFOPATH=/usr/local/MYLIB/foobar/man:$INFOPATH
export INFOPATH
Makefiles contain recipes which describe how to build outputs from sources.
If a directory has a file named Makefile
, you can run make TARGET
to make a certain output.
Makefiles have their own weird syntax. Most of the useful documentation is in the info pages.
Use info make
or the vinfo make
alias.
Sources may alternatively be called prerequisites or inputs.
Outputs may alternatively be called targets.
The basic syntax looks like this:
output.o: source.cpp
g++ source.cpp -o output.o
Variables are assigned similar to shell variables: MYVAR=value
.
You can also do shell expansion there: MARKDOWNS=$(shell *.md)
.
To access variables, you need to keep the "$()": echo MYVAR is: $(MYVAR)
.
There are some variable names which take convenient values for the current recipe.
$@ # target file name
$% # target member name, when the target is an archive memeber
$< # first prerequisite
$^ # list of all prerequisites
$^ # list of all prerequisites with duplicates
$? # all prerequisites newer than the target
$| # order-only prerequisites
$* # stem that an implicit rule matches
Similarly, variables for just the file name or the directory name can be constructed by appending F
or D
.
For example, if $@
is dir/foo.o
, then $(@D)
is dir
and $(@F)
is foo.o
.
This is hecka useful if you know you're going to be away from da innanetz and want to study.
httrack
is the tool to use.
$ httrack http://www.seas.upenn.edu/~cis194/spring15/
If you want, you can make Python pretend to be a server.
$ python3 -m http.server
If you don't have Python 3, it would be python -m SimpleHTTPServer
.
filename=$(basename "$pathname") # remove the leading directories
extension="${pathname##*.}" # remove everything but the [last] extension
noextension="${pathname%.*}" # remove the [last] extension
For clarity, here's an example using Zsh. I think it should be the same with any POSIX shell.
~
$ pathname=/tmp/bungus.tar.gz
~
$ basename $pathname
bungus.tar.gz
~
$ echo ${pathname##*.}
gz
~
$ echo ${pathname%.*}
/tmp/bungus.tar
I had a bunch of book chapters as PDF
s that I wanted to merge together, but they were named "Chapter-10-..." and the like. So, I couldn't simply rely on the default sorting of ls
.
So, I used
pdfunite `ls Front*; ls Copy*; ls Pre*; ls Chap* | sort -t - -k 2 -n; ls Ind*` arfken.pdf
-t -
specifies that fields are delimited by dashes. -k 2
specifies that the second field should be used for sorting. -n
specifies that sorting should be done by numeric value (as opposed to sorting alphabetically like ...17,18,19,1,20,21... or something).
tlmgr search --global --file myDependency.sty
tlmgr search --global myPackage
kpsewhich
is very similar to the which
built-in for Bash.
It shows you the locations for a given LaTeX file.
For example, kpsewhich article.cls
tells you where the article class is located.
Normally, pandoc adds a bunch of coloring information and header crap to files that have code blocks (verbatim environment) that makes the end LaTeX non-human-readable. You can fix this by simply adding the --listings
flag, which tells pandoc that you want to use the listings
package, rather than put custom coloring on every keyword (seriously).
It's really worth noting, however, that pandoc gives you only the body of the text. There's no preable, \begin{docuemnt}
, or \end{document}
.
You can get a standalone document by using the --standalone
flag.
pandoc mydoc.md --listings -o mydoc_body.tex
Put them in the YAML header like this:
---
title: 3D Printing Checklist
date: \today
fontsize: 12pt
documentclass: article
classoption: twocolumn
geometry: margin=0.75in
numbersections: true
#toc: true
pagestyle: plain
output:
pdf_document:
latex_engine: xelatex
---
It's often useful to be able to monitor the contents of a file. For example, to watch for when lines are added to a log file.
There are a few ways to accomplish this: watch
, tail -F
, and pressing F
in less
.
watch
can be used to monitor many things, not just files.
For example, watch tail myfile.log
will rerun tail myfile.log
every 2 seconds, while watch -n 1 echo
will act as a crude clock, and watch ls /tmp
will monitor the contents of /tmp
.
tail -F
simply displays new lines as they are added.
Pressing F
in less
is the same idea as tail -F
. This is probably the most powerful way to monitor a log file, since you get all the tools normally included in less
. The only downside is that you can't use them while monitoring. You have to press F
to start monitoring, and ctrl+c
to stop monitoring and return to normal viewing.
encrypt a device (or partition):
cryptsetup -y -v -h sha256 luksFormat /dev/sdb
Get header information about an encrypted device:
cryptsetup luksDump /dev/sdb
Decrypt a LUKS device and map it as a bulk storage device:
cryptsetup luksOpen /dev/sdb cry
Get the status of a mapped LUKS device:
cryptsetup -v status cry
Write zeroes to the device (optional, hides locations of future data):
dd if=/dev/zero of=/dev/mapper/cry
Set up a file system on the mapped LUKS device:
mkfs.ext4 /dev/mapper/cry
Mount the mapped LUKS device:
mkdir ~/cry
mount /dev/mapper/cry ~/cry
Change permissions so it can be used without root/sudo (after decrypting and mounting):
chown -R joedang ~/cry
Unmount:
umount ~/cry
Stop on-the-fly decryption of a LUKS device:
cryptsetup luksClose cry
This all assumes the encrypted version is called .secure
, the unencrypted version is secure
and they are both in the working directory.
mkdir .secure secure
sudo mount -t ecryptfs .secure secure
This will ask you for a passphrase and encryption setup stuff. It doesn't create any record of that setup, so you'll have to re-enter that every time. The defaults are sane, but filename encryption is a good idea to turn on.
mount: encfs .secure secure
umount: fusermount -u secure
I'm pretty sure this is caused by slock
.
Killing slock from a virtual terminal should solve it. (pkill slock
)
pkill -u joedang
will kill all processes belonging to the user joedang
, effectively logging them out.
If you're logged into another session as joedang
, you'll be logged out too.
You can check what's going to get killed by pkill
by running pgrep -u joedang -l
.
The -l
option prints the name of the process in addition to the process ID.
The default is to print the process ID alone.
strings myfile.asdf
will show you the printable characters in a file.
This is useful for getting information from proprietary binary files.
binwalk myfile.asdf
searches files for embedded files and executables.
It's kind of like a more powerful/general version of strings
.
fdisk -l
is useful for seeing information about attached disks.
The terminology around partitions is kind of confusing at first. The items with emphasis are specific pieces of jargon with distinct meanings.
Partition tables, are global to a physical drive. They describe where the various partitions are. There are different partition table types. The major types are MBR (aka msdos or dos) and GPT (aka GUID) These are also referred to as disklabel types.
Partitions are sections of storage space. The partition type is a hint in the partittion table to the OS on how to handle the stuff at a particular address referred to in the partition table. Confusingly, many partition types are named after partition table types or file system types! These don't necessarily matter, if the OS is able to figure things out from the file system.
File systems are a way of keeping track of... files. They can incorporate things like file permissions, journaling, data recovery, and encryption.
cfdisk
is a convenient tool for managing partitions.
gparted
is the GUI equivalent of cfdisk
.
gnome-disks
is also useful, but far less capable.
A Master Boot Record (MBR) is the old style of pointing to bootable partitions. It's meant to be used with BIOS firmwares. It's usually more compatible, but limits you to 4 partitions. If you want more, you need to use logical partitions. Some softwares call this a "dos" partition.
A GUID Partition Table is the new style. It's meant to be used with UEFI firmwares. It's usually not compatible with old hardware, but you can have lots of partitions.
The mkfs.*
commands can be used to format a partition to a particular file system.
gnome-disks
can also be used.
You can create a "Linux swap" partition and format it with mkswap
.
Then, if you use swapon
, you can start using that partition as a swap.
This lets Linux use it like RAM, if you happen to run out of actual RAM.
Obviously, this is much slower, and seriously effects performance when it is used,
but at least it prevents crashes!
The File System TABle (fstab) is located at /etc/fstab
.
Entries in fstab will automatically be mounted to the file system.
It usually contains comments hinting at its syntax.
man fstab
can provide a detailed explanation.
Here's an example of fstab contents:
# <file system> <mount point> <type> <options> <dump> <pass>
# / was on /dev/sda2 during installation
UUID=c87dcf2c-bef5-4e7d-a4a0-cbd30cbaea5f / ext4 discard,relatime,errors=remount-ro 0 1
The <file system>
field can be a device name, like /dev/sda1
, however this is generally inferior to using a UUID.
Device names are generated dynamically, whereas a UUID never changes. (unless the device is reformatted?)
You can determine the UUID of a partition with ls -l /dev/disk/by-partuuid
.
If available, genfstab -U
will automatically generate a vaid fstab of everything currently mounted.
fdisk -l
will also tell you the UUID of your disks.
when you need to apply grub updates:
grub-install /dev/sda
(or whatever drive, sda, sdb, et cetera...)
grub-mkconfig -o /boot/grub/grub.cfg
The usual way to create a live USB is to start with a live image and use some tool to install it on a USB drive. Most of the popular distros will provide a live image. In fact, the preferred way to install many distros is to start with a live USB, using the live version of the distro to bootstrap the installer.
There are a lot of tools available for creating live USBs.
The one I prefer is unetbootin
.
Starting with a function USB stick, open unetbootin (requires sudo), point it
towards the image you want to use, point it towards the drive, and let it do its
thing.
You can use pgrep
and pkill
to find and kill processes by their command name.
Typically, I'll just do pgrep -l mycommand
to confirm that only the intended processes will be selected.
Then, I'll do pkill mycommand
. Note that this only sends the TERM
signal, which politely asks the process to stop.
If the process is really pathological, you can use pkill -KILL mycommand
or kill -KILL PID
(PID is the process ID of the thing you want to kill.)
This tells the Linux kernel to stop the process in a non-graceful way.
ps axo pid,ppid,comm | grep mycommand
is also useful for finding the parent process of a misbehaving program,
so you can determine what started it.
Often, misbehaving processes are doing so because their parent process terminated, but they are still running. AFAIK, these always get their parent reassigned to PID 1, which is the init system. This can make it difficult to figure out what went wrong.
The brute-force solution is pkill xfce
. This will nuke XFCE and its child processes.
The more elegant solution would be the following, which actually tells XFCE to logout the user on that display.
Of course, this only works if XFCE is responding.
export DISPLAY=':0.0'
xfce4-session-logout --logout
You can try out a desktop environment by doing startx myEnvironment
from a virtual terminal.
For example, Ctrl+Alt+F1 to switch to VT 1 and then startx i3
to start i3.
screenfetch
gives ASCII art of your distro's logo along with statistics.
aview
and asciiview
(both provided by the aview
package) are nice interactive tools for creating ASCII art from images.
figlet
and toilet
are tools for converting plain text into ASCII banners of different fonts and colors.
cowsay
makes speech bubbles with text said by a cow.
cmatrix
is basically a screensaver like the stuff from The Matrix.
I have a tl;dr of color codes in dotfiles/bin/colorCodes
.
man console_codes
provides a reference for how all the codes work.
espeak
misfortune
chooses random fortunes.
rig
generates random identities with valid state/city/zip fields.
backronym
(my own Python script) generates random backronyms, given an acronym.
advent
is, of course, a classic.
frotz
plays a common format of text adventures.
You can get them here and here.
modprobe
and friends will help you manage kernel modules.
Notably, modprobe -c
will list what's installed and modprobe MODULE_NAME
will install a module.
Sometimes, after getting a kernel update, you'll get errors related to kernel modules not being available. For example, you update your kernel and then install a package that implicitly installs a module. To address this, you should try rebooting, so you're using the newer kernel.
In Firefox, go to about:config
in the address bar and add a string variable called general.useragent.override
.
Simply paste in a string that corresponds to another browser.
You can get a list of known useragent strings can be found here: http://www.useragentstring.com/pages/useragentstring.php
.
/connect freenode
to connect to the Freenode server./join #coreboot
to join a room.- Alt+Up or Alt+Down to switch between buffers.
/quit
to close Weechat completely.