Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
9b89c20c8a
|
|||
|
5398d3fb29
|
|||
|
4d926e8213
|
|||
|
5cb141942e
|
|||
|
42e46d0834
|
|||
|
474fbb84c2
|
|||
|
ebbc9ae1c8
|
|||
|
71ef311c70
|
|||
|
dc00b6ceea
|
|||
|
f3c7f931c4
|
|||
|
7f9de785df
|
|||
|
723024db0b
|
@@ -5,6 +5,7 @@ tags: [ "fun" ]
|
||||
|
||||
- `asciiquarium`
|
||||
- `cbonsai -lim "$(fortune)"`
|
||||
- `printf 'w\na\n' | ssh -tt nethack@alt.org`
|
||||
|
||||
```sh
|
||||
cow=$(cowsay -l | sort -R | head -1)
|
||||
|
||||
@@ -30,6 +30,11 @@ Done
|
||||
- If you have a command, Control + d will execute the command.
|
||||
- If you have nothing, `exit`.
|
||||
|
||||
Clear Search Highlights
|
||||
=======================
|
||||
|
||||
`<Esc>+u`
|
||||
|
||||
Input Run-Commands (`~/.inputrc`)
|
||||
=================================
|
||||
|
||||
|
||||
@@ -44,11 +44,24 @@ You can get an RSS feed from any YouTube video with this script:
|
||||
```
|
||||
#!/bin/sh
|
||||
|
||||
CHANNEL_ID="$(curl -s "$1" | tr ',' '\n' | grep -Po 'channelId":"\K[\w+-]+' | tail -1)"
|
||||
FEED_URL="https://www.youtube.com/feeds/videos.xml?channel_id=$CHANNEL_ID"
|
||||
CHANNEL_NAME="$(curl -s "$FEED_URL" | grep -m 1 -Po 'title\>\K[\w\s]+')"
|
||||
set -e
|
||||
|
||||
printf '%s "%s"\n' "$FEED_URL" "$CHANNEL_NAME"
|
||||
db=~/rec/feeds.rec
|
||||
|
||||
rec="${2:-$db}"
|
||||
|
||||
[ ! -z "$1" ] || {
|
||||
echo "Give me a youtube URL"
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ -w "$rec" ] || touch "$rec"
|
||||
|
||||
CHANNEL_ID="$(curl -s "$1" | tr ',' '\n' | grep -Po 'channelId":"\K[\w+-]+' | tail -1)"
|
||||
URL="https://www.youtube.com/feeds/videos.xml?channel_id=$CHANNEL_ID"
|
||||
Name="$(curl -s "$URL" | grep -m 1 -Po 'title\>\K[\w\s]+')"
|
||||
|
||||
recins --verbose -t Feed -f Name -v "${Name}" -f URL -v "${URL}" -f Category -v Videos -f Rating -v 3 -f Working -v yes "$rec"
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "pass"
|
||||
tags: [ "data" ]
|
||||
tags: [ "data", "credentials", "secrets" ]
|
||||
requires: "GPG Basics"
|
||||
---
|
||||
|
||||
|
||||
48
data/pass_otp.md
Normal file
48
data/pass_otp.md
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: "pass with otp"
|
||||
tags: [ "data", "credentials", "secrets", "2fa", "otp" ]
|
||||
requires: "pass"
|
||||
---
|
||||
|
||||
Need a Microsoft or Google authenticator?
|
||||
No you don't.
|
||||
|
||||
These usually come in the form of QR codes.
|
||||
|
||||
|
||||
```qr code
|
||||
|
||||
|
||||
█▀▀▀▀▀█ ▀ ▀▀▀ ▀ ▄ █▀▀▀▀▀█
|
||||
█ ███ █ ▄▄▀▄▄▀▄▄▀ █ ███ █
|
||||
█ ▀▀▀ █ ██ ▀▄██▀▀ █ ▀▀▀ █
|
||||
▀▀▀▀▀▀▀ █ █▄▀ █ █ ▀▀▀▀▀▀▀
|
||||
█▄▄ █▄▀▀██ ▄▄▀▀▄██▀▀██ ▄▀
|
||||
▄██▄▀█▀█ ▀▄▀ █▀▀▀█ ▀▀▀█▄
|
||||
▄ ▄▄█ ▀▀ ▄▄▀▀█▄█ ▀▀ ▄▀▀█▀
|
||||
█ ▀ ▀▀█▀▀ ▄ ▄█▀▄▀██▀█▄
|
||||
▀▀▀ ▀ ▀ █▄▄▀▄▀▀▄█▀▀▀█▀▀
|
||||
█▀▀▀▀▀█ ▀▄ █▀█▀ █ ▀ █▄▄
|
||||
█ ███ █ ▀ ▄ ▀█▄ ████▀▀█▄█
|
||||
█ ▀▀▀ █ ▄▀ ▄ ▄▄ ██▄▄█▄█
|
||||
▀▀▀▀▀▀▀ ▀ ▀▀ ▀▀▀ ▀▀ ▀▀▀
|
||||
|
||||
|
||||
```
|
||||
|
||||
Download the code, and get the information out:
|
||||
|
||||
|
||||
```sh
|
||||
zbarimg qr.png
|
||||
otp="$(zbarimg qr.png | sed 's/QR-Code://')"
|
||||
otp_name=site.org.otp
|
||||
echo "${otp}" | pass otp add --echo "${otp_name}"
|
||||
```
|
||||
|
||||
Show the OTP:
|
||||
|
||||
|
||||
```sh
|
||||
pass otp "${otp_name}"
|
||||
```
|
||||
65
data/recfiles/nginx_logs.md
Normal file
65
data/recfiles/nginx_logs.md
Normal file
@@ -0,0 +1,65 @@
|
||||
---
|
||||
title: "nginx logs with recfiles"
|
||||
tags: [ "data", "recfiles", "logs" ]
|
||||
requires: [ "Recfiles", "nginx" ]
|
||||
---
|
||||
|
||||
The standard `nginx` log format has such a lack of consistency or meaning that you might squint your face into a whirlpool making sense of them:
|
||||
|
||||
|
||||
```nonsense
|
||||
18.97.14.85 - - [16/Nov/2025:00:52:12 +0100] "GET /posts/learning_without_experts/content.html HTTP/1.1" 200 1704 "-" "CCBot/2.0 (https://commoncrawl.org/faq/)"
|
||||
57.141.0.25 - - [16/Nov/2025:00:52:18 +0100] "GET /posts/hope_you_win/ HTTP/1.1" 200 61997 "-" "meta-externalagent/1.1 (+https://developers.facebook.com/docs/sharing/webmasters/crawler)"
|
||||
201.17.157.249 - - [16/Nov/2025:00:52:19 +0100] "GET https://ttrpgs.com/post/wp/ HTTP/1.1" 200 45202 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
|
||||
47.246.164.151 - - [16/Nov/2025:00:52:22 +0100] "GET https://ttrpgs.com/css/styles.dc38388a8f0b890e788bd3a99b7495d14e7d5ac4359ed3b49abeb778497863b284ad4cc7e496ef58c84139295f9bafed82f5a41345eda86bd2d429cccb7c2596.css HTTP/1.1" 200 27109 "https://ttrpgs.com/post/wp/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
|
||||
47.246.164.154 - - [16/Nov/2025:00:52:22 +0100] "GET https://ttrpgs.com/fonts/Metropolis-MediumItalic.woff2 HTTP/1.1" 200 28100 "https://ttrpgs.com/css/styles.dc38388a8f0b890e788bd3a99b7495d14e7d5ac4359ed3b49abeb778497863b284ad4cc7e496ef58c84139295f9bafed82f5a41345eda86bd2d429cccb7c2596.css" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
|
||||
47.246.164.135 - - [16/Nov/2025:00:52:22 +0100] "GET https://ttrpgs.com/fonts/Metropolis-Regular.woff2 HTTP/1.1" 200 24152 "https://ttrpgs.com/css/styles.dc38388a8f0b890e788bd3a99b7495d14e7d5ac4359ed3b49abeb778497863b284ad4cc7e496ef58c84139295f9bafed82f5a41345eda86bd2d429cccb7c2596.css" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
|
||||
```
|
||||
|
||||
Someone created this logging format on purpose, to make sure nobody could parse it with a hundred `column`, `cut`, or `awk` pipes.
|
||||
|
||||
The problem lies in `/etc/nginx/nginx.conf`:
|
||||
|
||||
|
||||
```conf
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
```
|
||||
|
||||
Despite a request of three strings, this format returns one string.
|
||||
|
||||
It can output to recfile format like this:
|
||||
|
||||
|
||||
```conf
|
||||
log_format main '\nIP: $remote_addr\n'
|
||||
'User: $remote_user\n'
|
||||
'Date: $time_local\n'
|
||||
'Request: $request\n'
|
||||
'Status: $status\n'
|
||||
'Bytes: $body_bytes_sent\n'
|
||||
'Referrer: $http_referer\n'
|
||||
'Agent: $http_user_agent\n'
|
||||
'XForward: $http_x_forwarded_for\n';
|
||||
|
||||
access_log /var/log/nginx/access.rec main;
|
||||
```
|
||||
|
||||
Note the newline (`\n`) symbol, required to start a new entry on a new line.
|
||||
|
||||
1. `cp /etc/nginx.conf /etc/nginx.conf.bak`
|
||||
1. Change `/etc/nginx.conf` to match the format above.
|
||||
1. Check the file works with `nginx -t`.
|
||||
1. Restart the `nginx` service.
|
||||
1. Access that web page to make sure that at least one log exists.
|
||||
1. Check the file with `recfix /var/log/nginx/access.rec`.
|
||||
|
||||
Once it works, you can add the usual recfile headers:
|
||||
|
||||
|
||||
```sh
|
||||
sed -i '1 i \ ' /var/log/nginx/access.rec
|
||||
sed -i '1 i %rec: Weblog' /var/log/nginx/access.rec
|
||||
sed -i '2 i %doc: nginx access logs' /var/log/nginx/access.rec
|
||||
```
|
||||
@@ -6,8 +6,9 @@ requirements: [ "pacman" ]
|
||||
|
||||
```sh
|
||||
pacman --sync --noconfirm --needed base-devel gcc git
|
||||
git clone https://aur.archlinux.org/yay.git /tmp/yay
|
||||
makepkg -C !$ -si
|
||||
git clone https://aur.archlinux.org/yay.git
|
||||
cd yay
|
||||
makepkg -si
|
||||
```
|
||||
|
||||
The flags are mostly the same as in `pacman`.
|
||||
|
||||
@@ -22,6 +22,12 @@ Search with regex:
|
||||
xbps-query --regex -Rs 'cow(s)?\w'
|
||||
```
|
||||
|
||||
Search for `genfstab`:
|
||||
|
||||
```sh
|
||||
xlocate genfstab
|
||||
```
|
||||
|
||||
List what's required for cowsay
|
||||
|
||||
```sh
|
||||
|
||||
83
sound/mpd_pipewire.md
Normal file
83
sound/mpd_pipewire.md
Normal file
@@ -0,0 +1,83 @@
|
||||
---
|
||||
title: "mpd"
|
||||
tags: [ "sound", "pipewire" ]
|
||||
requirements: [ "pipewire" ]
|
||||
---
|
||||
# Setup
|
||||
|
||||
## Configuration
|
||||
|
||||
This is a minimum configuration file for /etc/mpd.conf
|
||||
|
||||
> music_directory "/var/lib/mpd/music"
|
||||
>
|
||||
> playlist_directory "/var/lib/mpd/playlists"
|
||||
>
|
||||
> db_file "/var/lib/mpd/mpd.db"
|
||||
>
|
||||
>
|
||||
> pid_file "/run/mpd/mpd.pid"
|
||||
>
|
||||
> state_file "/var/lib/mpd/mpdstate"
|
||||
>
|
||||
>
|
||||
> user "mpd"
|
||||
>
|
||||
> audio_output {
|
||||
> type "pulse"
|
||||
> name "My Pulse Output"
|
||||
> }
|
||||
>
|
||||
|
||||
## Set Pulseaudio to Run System-Wide
|
||||
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /etc/pipewire/pipewire-pulse.conf.d
|
||||
|
||||
cat > /etc/pipewire/pipewire-pulse.conf.d/pulse-server.conf << "EOF"
|
||||
pulse.properties = {
|
||||
server.address = [
|
||||
"unix:native"
|
||||
"tcp:4713" # IPv4 and IPv6 on all addresses
|
||||
]
|
||||
}
|
||||
EOF
|
||||
|
||||
|
||||
```
|
||||
|
||||
Give `mpd` access to pulse:
|
||||
|
||||
```sh
|
||||
grep pulse /etc/group | cut -d: -f1
|
||||
|
||||
grep pulse /etc/group | cut -d: -f1 | while read g; do
|
||||
sudo usermod -aG $g mpd
|
||||
done
|
||||
```
|
||||
|
||||
Working with mpd will be easier if you have access to its files, so maybe:
|
||||
|
||||
```sh
|
||||
sudo usermod -aG mpd $USER
|
||||
```
|
||||
|
||||
Remember to reboot.
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
Check pulse is working.
|
||||
|
||||
```sh
|
||||
ss | grep 4713
|
||||
```
|
||||
|
||||
# Notifications (AUR)
|
||||
|
||||
Install `mpd-notification` and then start the service:
|
||||
|
||||
```sh
|
||||
systemctl --user enable mpd-notification
|
||||
```
|
||||
|
||||
12
sound/pipewire.md
Normal file
12
sound/pipewire.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
title: "pipewire"
|
||||
tags: [ "sound" ]
|
||||
---
|
||||
|
||||
Install `wireplumber` and `pipewire`, then add your user to any `pipewire` group.
|
||||
|
||||
```sh
|
||||
sudo ln -s /usr/share/examples/pipewire/20-pipewire-pulse.conf /etc/pipewire/pipewire.conf.d/20-pipewire-pulse.conf
|
||||
|
||||
sudo ln -s /usr/share/examples/wireplumber/10-wireplumber.conf /etc/pipewire/pipewire.conf.d/10-wireplumber.conf
|
||||
```
|
||||
@@ -14,12 +14,27 @@ Say 'hello' to yourself:
|
||||
ansible --module-name=ping localhost
|
||||
```
|
||||
|
||||
Ansible takes a lot of information about each machine during setup:
|
||||
|
||||
```sh
|
||||
TMP=$(mktemp)
|
||||
ansible --module-name=setup localhost | tee $TMP
|
||||
less !$
|
||||
```
|
||||
|
||||
If you have `jq`, you can pull out info:
|
||||
|
||||
```sh
|
||||
sed -i 's/.*SUCC.*/{/' $TMP
|
||||
jq '.ansible_facts.ansible_distribution' < $TMP
|
||||
```
|
||||
|
||||
Upgrade through the package manager.
|
||||
|
||||
`packager=apt` (or `pacman` or `xbps`,...)
|
||||
|
||||
```sh
|
||||
packager=apt
|
||||
packager="$( jq -r '.ansible_facts.ansible_pkg_mgr' < $TMP )"
|
||||
ansible --module-name=${packager} --args "upgrade=yes" localhost
|
||||
```
|
||||
|
||||
@@ -87,4 +102,8 @@ ansible-inventory --list -y -i
|
||||
ansible-vault view sec.yml --vault-pass-file pass.sh
|
||||
```
|
||||
|
||||
community.general.say voice=en_GB msg="Testing 123"
|
||||
Install `espeak', then make the computer say something:
|
||||
|
||||
```sh
|
||||
ansible --module-name=say --args "msg='testing'" localhost
|
||||
```
|
||||
|
||||
71
vision/record_terminal.md
Normal file
71
vision/record_terminal.md
Normal file
@@ -0,0 +1,71 @@
|
||||
---
|
||||
title: "Record a Terminal Session"
|
||||
tags: [ "vision", "share" ]
|
||||
---
|
||||
|
||||
Record a terminal command, then press 'Control + d' to exit.
|
||||
|
||||
```sh
|
||||
script --timing=time.log stat.txt
|
||||
ls -a
|
||||
ls -al
|
||||
stat ~/.bashrc
|
||||
^D
|
||||
```
|
||||
|
||||
Replay the session:
|
||||
|
||||
```sh
|
||||
scriptreplay --timing=time.log stat.txt
|
||||
```
|
||||
|
||||
Try a bare command, without any timing:
|
||||
|
||||
```sh
|
||||
script -c 'top | lolcat' loltop
|
||||
nl loltop
|
||||
```
|
||||
|
||||
Has your terminal messed up?
|
||||
Is the cursor hiding?
|
||||
Reset it!
|
||||
|
||||
```sh
|
||||
reset
|
||||
```
|
||||
If you can't see any keys, keep typing anyway: have faith in your terminal.
|
||||
|
||||
This `loltop` file will not play properly as it has no timings file.
|
||||
But you can cheat the system and use your other timings file:
|
||||
|
||||
```sh
|
||||
scriptreplay --timing=time.log loltop
|
||||
```
|
||||
|
||||
This will mostly not work well, but it shows how the timing file works:
|
||||
|
||||
|
||||
```text
|
||||
0.033401 23
|
||||
0.044513 8
|
||||
0.000016 219
|
||||
1.349324 114
|
||||
0.179106 1
|
||||
0.088790 1
|
||||
0.072821 1
|
||||
0.358337 2
|
||||
0.000254 9
|
||||
0.004720 52
|
||||
0.000084 21
|
||||
0.155462 671
|
||||
```
|
||||
|
||||
I think it works like this?
|
||||
|
||||
| How long it took | to type *n* characters |
|
||||
|:----------------:|:----------------------:|
|
||||
| 0.033401 | 23 |
|
||||
| 0.044513 | 8 |
|
||||
| 0.000016 | 219 |
|
||||
| 1.349324 | 114 |
|
||||
|
||||
32
writing/vim/linewrap.md
Normal file
32
writing/vim/linewrap.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
title: "vim windows"
|
||||
tags: [ "vim", "format", "linewrap" ]
|
||||
requires: [ "vim basics" ]
|
||||
---
|
||||
|
||||
Wrap lines in a file to 80 characters with `gqG`.
|
||||
|
||||
Take this markdown file:
|
||||
|
||||
|
||||
```markdown
|
||||
This is a looooooooooooooooooooooooong line, and reeeeeeeeeeeeeeding it can be a paaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaiiiiiiiiiiiiin in the aaaaaaaaaaaaaaaaaaaaaaaarse.
|
||||
```
|
||||
|
||||
Reformat the line to the proper text width by pressing `gqw`.
|
||||
The output looks like this:
|
||||
|
||||
```markdown
|
||||
This is a looooooooooooooooooooooooong line, and reeeeeeeeeeeeeeding it can be
|
||||
a paaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaiiiiiiiiiiiiin in the
|
||||
aaaaaaaaaaaaaaaaaaaaaaaarse.
|
||||
```
|
||||
|
||||
This works with chunks of text in visual mode.
|
||||
|
||||
Change what width the text should be:
|
||||
|
||||
```vim
|
||||
:set textwidth=100
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "vim search"
|
||||
tags: [ "vim", "search" ]
|
||||
title: "find and replace"
|
||||
tags: [ "vim", "search", "replace", "find" ]
|
||||
requires: [ "vim basics" ]
|
||||
---
|
||||
Search for the next and or previous occurrence of the word under your cursor with `*` and `#`.
|
||||
@@ -9,7 +9,11 @@ Search and replace the first 'one' found with 'two':
|
||||
|
||||
`:%s/one/two/`
|
||||
|
||||
Same, but replace 'one' globally:
|
||||
Run the last substitution globally:
|
||||
|
||||
`g&`
|
||||
|
||||
Same, but just replace 'one' globally:
|
||||
|
||||
`:%s/one/two/g`
|
||||
|
||||
Reference in New Issue
Block a user