Анализ страницы https://wizardzines.com/comics
Основное Готовность: 100%
Домен
wizardzines.com
Состояние доменного имени
?
Проверяем корректность доменного имени и наличие технических проблем на уровне домена.
Домен второго уровня идеален для продвижения.
Отличный запоминающийся домен.
Ответ сервера
200 Успешный ответ
HTTP-код ответа и цепочка редиректов
?
Код 200 — страница доступна. Коды 3xx — редиректы (цепочки замедляют загрузку и размывают ссылочный вес). Коды 4xx/5xx — ошибки, поисковик не сможет проиндексировать страницу.
Сервер настроен корректно.
Цепочка редиректов:
https://wizardzines.com/comics
301 MovedPermanently
https://wizardzines.com/comics/
200 OK
Безопасность
Сайт безопасен
Использование HTTPS и SSL-сертификат
?
HTTPS — обязательный стандарт. Google и Яндекс отдают предпочтение защищённым сайтам. Отсутствие SSL или просроченный сертификат ведут к предупреждениям в браузере и снижению позиций.
На сайте работает защищенный протокол ssl и сайт открывается по https.
Ssl-сертификат действителен до 04.10.2026 22:45:22.
Включён HSTS (Strict-Transport-Security) — защита от подмены на http.
Поздравляем! Сайт не содержится в реестре РКН.
Кодировка
utf-8
Кодировка символов страницы
?
Стандарт — UTF-8. Неправильная кодировка вызывает нечитаемые символы и мешает поисковику корректно распознать текст страницы.
Указана кодировка на странице utf-8.
Язык
Атрибут lang в HTML-теге
?
Атрибут lang (<html lang="ru">) сообщает поисковикам и браузерам, на каком языке написана страница. Помогает при ранжировании в региональном поиске.
Язык страницы не указан. Рекомендуется явно указать язык документа!
Скорость загрузки
~0,63сек
Время отклика сервера (TTFB)
?
Time To First Byte — время до получения первого байта от сервера. Норма до 200 мс. Медленный отклик ухудшает пользовательский опыт и ранжирование: Яндекс и Google учитывают скорость страниц.
Скорость загрузки сайта 0,63сек оптимальна.
Объем документа
543Кб
Размер HTML-кода страницы
?
Слишком большой HTML замедляет парсинг браузером и сканирование поисковым роботом. Рекомендуется не более 200 Кб.
Объем html-документа 543Кб оптимален.
Структура html-документа корректна.
Ресурсы
Ресурсы: 6
Внешние ресурсы страницы (CSS, JS, изображения)
?
Количество и тип подключённых ресурсов влияют на скорость загрузки. Большое число запросов увеличивает время рендеринга страницы.
Кол-во файлов ресурсов 6 достаточно.
Показать полный список ресурсов
| Тип | Название | Значение |
|---|---|---|
| stylesheet | text/css | //fonts.googleapis.com/css?family=Source+Sans+Pro:400,300|Montserrat:700 |
| stylesheet | https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;700;800&display=swap | |
| stylesheet | /css/style.css | |
| js | https://plausible.io/js/pa-voly1ZSJVJfUTomsqJDt-.js | |
| js | /js/list.min.js | |
| js | /js/comic-search.js |
Серверные заголовки
Кол-во: 12
HTTP-заголовки ответа сервера
?
Заголовки сервера передают браузеру и поисковику служебную информацию: кеширование, безопасность (CSP, HSTS), сжатие (gzip). Правильная настройка ускоряет загрузку и повышает защищённость.
Найдены серверные заголовки 12шт. Подробнее про серверные заголовки.
Показать полный список серверных заголовков
| Ключ | Значение |
|---|---|
| Accept-Ranges | bytes |
| Age | 0 |
| Cache-Control | public, must-revalidate, max-age=0 |
| cache-status | "Netlify Edge"; fwd=miss; fwd-status=200; stored |
| Date | Sat, 22 Aug 2026 17:36:31 GMT |
| ETag | "c085c12cd3462a5140b68ff8d74fe3a5-ssl" |
| nel | {"report_to":"default","max_age":31536000,"include_subdomains":true} |
| report-to | {"group":"default","max_age":31536000,"endpoints":[{"url":"https://jvns.report-uri.com/a/d/g"}],"include_subdomains":true} |
| Server | Netlify |
| Strict-Transport-Security | max-age=31536000 |
| Vary | Accept-Encoding |
| x-nf-request-id | 01M0N8QAG8248XGX76YG4TCN1D |
CMS
Система управления сайтом (движок)
?
CMS — это движок, на котором работает сайт (WordPress, 1C-Bitrix, Tilda и др.). Знание CMS помогает понять возможности SEO-оптимизации и подобрать подходящие инструменты. «Не определена» — вероятно, самописный сайт или нестандартная сборка.
Сайт работает на CMS Tilda.
Веб-сервер
Netlify
Программное обеспечение сервера
?
Веб-сервер — это ПО, которое отдаёт страницы посетителям (nginx, Apache, IIS, LiteSpeed и др.). Определяется по серверным заголовкам ответа (Server, X-Powered-By и т.п.). «Не определён» — сервер намеренно скрывает эти заголовки, это нормальная практика безопасности.
В заголовке Server указано: Netlify.
Мета-теги Готовность: 48%
Title
Wizard Zines - Comics
Заголовок страницы в браузере и поисковой выдаче
?
Title — главный SEO-заголовок страницы. Влияет на CTR в поиске и ранжирование. Оптимальная длина: 50–70 символов. Ключевые слова — ближе к началу.
Необходимо увеличить число символов в title (текущее значение мало: 21, минимум: 25, оптимально: от 40 до 45)
Дублей словоформ в title не найдено.
Description
Описание страницы в поисковой выдаче (сниппет)
?
Meta Description — текст под заголовком в выдаче. Напрямую на позиции не влияет, но влияет на CTR. Оптимальная длина: 120–160 символов.
Установите мета-тег description!
Keywords
Список ключевых слов страницы (устаревший тег)
?
Meta Keywords не учитывается Яндексом и Google для ранжирования с 2009–2012 годов. Заполнение не обязательно, но не вредит. Конкурент может использовать содержимое для анализа.
Установите мета-тег keywords!
Канонический Url
Указывает поисковику основную версию страницы
?
Canonical (rel=canonical) предотвращает проблему дублей страниц. Должен точно совпадать с URL проверяемой страницы. Неправильный canonical может передать ссылочный вес на другую страницу.
Рекомендуем прописать канонический Url.
Robots
Ошибок нет
Директивы для поисковых роботов на уровне страницы
?
Meta Robots управляет индексацией конкретной страницы: index/noindex — индексировать ли, follow/nofollow — следовать ли по ссылкам. Noindex полностью исключает страницу из поиска.
Meta-тег robots не указан. Страница свободна для индексации.
Адаптивность
width=device-width, initial-scale=1, target-densityDpi=device-dpi
Настройка масштабирования на мобильных устройствах
?
Тег viewport (<meta name="viewport">) сообщает браузеру, как масштабировать страницу на мобильных. Стандарт: width=device-width, initial-scale=1. Отсутствие — признак отсутствия мобильной версии.
Meta-тег viewport со значением-константой width=device-width задаёт ширину страницы в соответствии с размером экрана.
Meta-тег viewport со значением initial-scale=1.0 определяет масштаб 1:1, т.е. «не масштабировать».
Разметка OpenGraph
Кол-во: 6
Мета-теги для красивых превью в соцсетях
?
OpenGraph (og:title, og:description, og:image) управляет тем, как страница выглядит при репосте в социальных сетях и мессенджерах. Отсутствие OG-тегов — невзрачный превью при шеринге.
Разметка OpenGraph задана. Страница оптимизирована под социальные сети.
Показать полный список og мета-тегов
| Тип | Значение |
|---|---|
| og:image | /images/main-og-image.png |
| og:site_name | wizard zines |
| og:title | Wizard Zines - Comics |
| og:url | https://wizardzines.com/comics/ |
| og:description | |
| og:type | website |
Все мета-теги
Кол-во: 15
Полный список мета-тегов страницы
?
Таблица всех meta-тегов, включая нестандартные. Позволяет найти опечатки, дубли и лишние теги.
Найдены мета-теги 15шт. Мета-теги не видимы для человека и предназначены для обмена информацией между веб-страницей и поисковыми системами, браузерами и другими веб-службами. С ними роботы 🤖 и устройства ведут себя более ожидаемо.
Показать полный список мета-тегов
| Тип | Название | Значение |
|---|---|---|
| name | viewport | width=device-width, initial-scale=1, target-densityDpi=device-dpi |
| name | generator | Hugo 0.145.0 |
| property | description | |
| property | mobile-web-app-capable | yes |
| property | apple-mobile-web-app-capable | yes |
| property | apple-mobile-web-app-status-bar-style | black |
| property | author | |
| property | twitter:site | @b0rk |
| property | twitter:creator | @b0rk |
| property | og:image | /images/main-og-image.png |
| property | og:site_name | wizard zines |
| property | og:title | Wizard Zines - Comics |
| property | og:url | https://wizardzines.com/comics/ |
| property | og:description | |
| property | og:type | website |
Оптимизация Готовность: 67%
Структура
Ошибок нет
Семантические HTML-элементы страницы
?
Проверяет наличие основных структурных элементов: nav, header, footer, main. Корректная семантическая структура помогает поисковику понять архитектуру страницы.
Структура документа корректна (теги <html> и <body> присутствуют в одном экземпляре).
Контент
Есть ошибки
Объём и качество текстового содержимого
?
Анализирует объём полезного текста на странице. Слишком мало — страница может считаться малополезной. Слишком много — ухудшается читаемость и восприятие.
Абзацев с текстом 2 слишком мало. Добавьте больше абзацев с текстом (тег <p>)!
Слова из title 3 встречаются в тексте достаточно.
Среднее число слов в абзаце 23 достаточно.
Кол-во знаков контента 413788 на странице оптимально.
Кол-во слов 73047 на странице оптимально.
Заголовки
Ошибок нет
Иерархия заголовков H1–H6
?
H1 должен быть один и содержать ключевой запрос. H2–H6 описывают подразделы. Пропуск уровней (H1 → H3) и несколько H1 — типичные ошибки, снижающие понятность страницы для поисковика.
На странице присутствуют заголовки <h1> 2. Это прекрасно.
На странице присутствуют заголовки <h3> 3.
Тошнота
15,94
Насколько одно слово доминирует в тексте
?
Классическая тошнота = √(частота самого повторяющегося слова). Норма до 7–8: текст воспринимается естественно. Выше — поисковик может счесть страницу переспамленной.
Тошнота превышает норму 5. Измените текст страницы!
Академич. тошнота
454,52%
Насколько текст перенасыщен ключевыми словами
?
Академическая тошнота = (частота слова / общее количество слов) × 100%. Показывает долю конкретного слова в тексте. Норма 5–15%.
Академическая тошнота превышает норму 5-15%. Измените текст страницы!
Семантическое ядро
20
Наиболее часто встречающиеся слова на странице
?
Топ слов по частоте использования. Показывает, какие слова доминируют в тексте с точки зрения поисковика.
Контент страницы содержит осмысленный текст и слова.
Показать список слов
| Слово | Кол-во | Частота |
|---|---|---|
| illustration | 254 | 0,35% |
| branch | 228 | 0,31% |
| labelled | 200 | 0,27% |
| figure | 188 | 0,26% |
| person | 185 | 0,25% |
| commit | 177 | 0,24% |
| program | 155 | 0,21% |
| represented | 146 | 0,20% |
| smiling | 136 | 0,19% |
| smiley | 131 | 0,18% |
| person: | 127 | 0,17% |
| example | 120 | 0,16% |
| terminal | 108 | 0,15% |
| doesnt | 103 | 0,14% |
| different | 94 | 0,13% |
| request | 93 | 0,13% |
| process | 92 | 0,13% |
| server | 90 | 0,12% |
| branches | 87 | 0,12% |
| programs | 85 | 0,12% |
Индексация Готовность: 50%
Индексирование
Есть ошибки
Разрешено ли индексирование страницы
?
Проверяет, не закрыта ли страница от индексации через robots.txt, meta robots или X-Robots-Tag. Страница, закрытая от индексации, не появится в поисковой выдаче.
Анкоров на странице 536 слишком много. Проведите ревизию и оптимизацию ссылок сайта.
Robots.txt
Найден корректный robots.txt
Файл управления сканированием сайта роботами
?
Robots.txt указывает поисковым роботам, какие страницы сканировать, а какие — нет. Ошибки в файле могут случайно закрыть важные разделы от индексации.
Robots.txt настроен корректно. Размер файла: 142 байт. Загружен за: 0сек.
Проверяемая страница не запрещена в robots.txt.
Robots.txt доступен по постоянному адресу
Показать содержимое robots.txt
User-agent: *
Disallow:
Sitemap: https://wizardzines.com/sitemap.xml
User-agent: GPTBot
Disallow: /
User-agent: Google-Extended
Disallow: /
Sitemap
Кол-во: 1
XML-карта сайта для поисковиков
?
Sitemap.xml помогает поисковику быстрее находить и индексировать страницы. Особенно важен для крупных сайтов и новых страниц, на которые ещё нет входящих ссылок.
Robots.txt содержит карту сайта. Это прекрасно!
Robots.txt не содержит ошибок в карте сайта.
Показать карту сайта
| Url | Статус |
|---|---|
| https://wizardzines.com/sitemap.xml |
|
Внутренние ссылки
Кол-во: 520
Ссылки на другие страницы своего сайта
?
Внутренние ссылки распределяют ссылочный вес между страницами и помогают поисковику обходить сайт. Пустые анкоры и ссылки на запрещённые robots.txt страницы — типичные ошибки.
Внутренних ссылок на странице 520 слишком много. Проведите оптимизацию сайта!
Внутренние ссылки не запрещены к индексации в robots.txt.
На странице присутствуют изображения 1.
Показать первые 100 внутренних ссылок
| Url | Анкор | Состояние |
|---|---|---|
| / |
<span class="star">★</span>
wizard zines
<span class="star">★</span>
|
|
| / |
home
|
|
| /comics |
comics
|
|
| /comics/bash-tricks/ |
<span class="title">
bash tricks
</span>
<div class="keywords"></div>
<div class="transcript">### panel 1: ctrl + r
search your history!
I use this **constantly** to rerun commands
### panel 2: magical braces
```$ convert file.{jpg,png}```
expands to
```$ convert file.jpg file.png```
`{1..5}` expands to 1 2 3 4 5
(for i in {1..100}...)
### panel 3: !!
expands to the last command run
`$ sudo !!`
### panel 4:
commands that start with a space don't go in your history. good if there's a password
### panel 5: loops
```
for i in *.png
do
convert $i $i.jpg
done
```
person: for loops: easy & useful!
### panel 6: $ ( )
gives the output of a command
``` $touch file- $ (date -1)```
create a file named file-2018-05-25
### panel 7: more keyboard shortcuts
ctrl + a beginning of line
ctrl + e end of line
ctrl + l clear the screen
& lots more emacs shortcuts too!</div>
|
|
| /comics/proc/ |
<span class="title">
/proc
</span>
<div class="keywords"></div>
<div class="transcript">### panel 1:
Every process on Linux has a PID (process ID) like 42.
In /proc/42, there's a lot of VERY USEFUL information about process 42.
### panel 2: /proc/PID/cmdline
command line arguments the process was started with.
### panel 3: /proc/PID/environ
all of the process's environment variables
### panel 4: /proc/PID lexe
Symlink to the process's binary magic: works even if the binary has been deleted!
### panel 5: /proc/PID/status
Is the program running or asleep? How much memory is it using? And much more!
### panel 6: /proc/PID/fd
Directory with every file the process has open!
Run ```$1s-1 /proc/42/fd``` to see the list of files for process 42.
These symlinks are also magic & you can use them to recover deleted files
### panel 7: /proc/PID/stack
The kernel's current stack for the process. Useful if it's stuck in a system call.
### panel 8: /proc/PID/maps
List of process's memory maps. Shared libraries, heap, anonymous maps, etc.
### panel 9: and more
Look at ```man proc``` for more information!
</div>
|
|
| /comics/better-at-debugging/ |
<span class="title">
how I got better at debugging
</span>
<div class="keywords"></div>
<div class="transcript">### Remember: the bug is happening for a logical reason.
It's never magic. Really. Even when it makes no sense.
### Be confident I can fix it
before: maybe this is too hard
now: well I've fixed a lot of hard bugs before
### Talk to my coworkers
person 1: ?
person 2: !
### know my debugging toolkit
before: I want to know $THING but I don't know how to find out
now: I KNOW! I'll use tcpdump!
### most importantly: I learned to like it
before: oh no! a bug!
now: I think I'm about to learn something
(facial expression: determination)</div>
|
|
| /comics/grep/ |
<span class="title">
grep
</span>
<div class="keywords"></div>
<div class="transcript">### panel 1:
grep lets you files for text search
```$ grep bananas foo.txt```
Here are some of my favourite grep command line arguments!
### panel 2: -E
Use if you want regexps like ".+" to work. otherwise you need to use ".\+"
### panel 3: -v
invert match find : all lines that don't match
### panel 4: -r
recursive! Search all the files in a directory.
### panel 5: -o
only print the matching part of the line (not the whole line)
### panel 6: -i
case insensitive
### panel 7:
-A -B -C
Show **c**ontext for your search
```$grep -A 3 foo```
will show 3 lines of context **a**fter a match
### panel 8: -l
only show the **filenames** of the files that matched
### panel 9: -F aka fgrep
don't treat the match string as a regex
eg ```$ grep -F...```
### panel 10: -a
search binaries: treat binary data like it's text instead of ignoring it!
### panel 11: grep alternatives
ack ag ripgrep
(better for searching code!)</div>
|
|
| /comics/permissions/ |
<span class="title">
permissions
</span>
<div class="keywords"></div>
<div class="transcript">### panel 1:
There are 3 things you can do to a file.
**r**ead **w**rite e**x**ecute
### panel 2:
Is -1 file.txt shows you permissions. Here's how to interpret the output:
rw- **bork** (user) can read & write
rw- **staff** (group) can read & write
r-- **ANYONE** can read
### panel 3: File permissions are 12 bits
First digit: setuid
Second digit: setgid
Third digit: sticky
User 110 rwx
Group 110 rwx
all 100 rwx
For files:
r = can read
W = can write
X = can execute
For directories, it's approximately:
r = can list files
W = can create files
x = can cd into & access files
### panel 4:
110 in binary is 6
so rw- = 110 = 6
r-- = 100 = 4
r-- = 100 = 4
```chmod 644 file.txt|```
means change the permissions to:
rw- r-- r--
Simple!
### panel 5:
setuid affects executables
```$1s-1/bin/ping```
rw**s** r-x r-x root root
the s means ping always runs as root
```setgid``` does 3 different unrelated things for executables, directories, and regular files.
person: unix! why??
unix: it's a long story
</div>
|
|
| /comics/wizard-programmer/ |
<span class="title">
how to be a wizard programmer
</span>
<div class="keywords"></div>
<div class="transcript"></div>
|
|
| /comics/more-bash-tricks/ |
<span class="title">
more bash tricks
</span>
<div class="keywords"></div>
<div class="transcript">### `cd -`
changes to the directory you were last in
`pushd` & `popd` let you keep a stack
### `ctrl + z`
suspends (SIGTSTP) the running program
### `fg`
brings backgrounded/suspended program to the foreground
### `bg`
starts suspended program & backgrounds it (use after `ctrl + z`)
### `shellcheck`
(with hearts around it)
shell script linter! helpes spot common mistakes
### `<( )`
(process substitution)
treat process output like a file (no more temp files!)
eg:
`$diff <(ls) <(ls -a)`
### `fc`
("fix command")
open the last command you ran in an editor
then run the edited version
### `type`
tells you if something is a builtin, program, or alias
try running type on
- time
- ping
- pushd
(they're all different types)
</div>
|
|
| /comics/ssh/ |
<span class="title">
ssh
</span>
<div class="keywords"></div>
<div class="transcript">### ssh keys
An ssh key is a secret key that lets you SSH to a machine
person: hello!
ssh: That's on my list of authorized keys! come in!
### ssh-copy-id
This script installs your SSH key on a host (over SSH)
`$ ssh-copy-id user@host`
(puts it in .ssh/authorized-keys etc)
installing a SSH key is surprisingly finicky so this script is helpful!
### port forwarding
```
ssh user@host.com - Nfl
3333:localhost:8888
```
3333 = local port
8888 = remote port
Lets you view a remote server that's not on the internet in your browser.
### just run 1 command
`$ ssh user@host uname -a`
runs the command `uname -a` & exits.
### ssh-agent
remembers your SSH key passphrase so you don't have to keep typing it
### ~.
<Enter> ~. closes the SSH , connection. Useful if it's hanging!
### mosh
ssh alternative: keeps the connection open if you disconnect + reconnect later
### .ssh/config
Lets you set, per host:
- Username to use.
- SSH key to use
- an alias!
so you can type `$ ssh ALIAS` instead of `ssh user@very longdomain.com`</div>
|
|
| /comics/1-1s/ |
<span class="title">
what to talk about in 1:1s
</span>
<div class="keywords">[manager]</div>
<div class="transcript">Each of these items is enclosed in a little thought bubble, with an image of a stick figure with short curly hair. The person is smiling in every illustration, except "what's not going well".
### what's been going well
I LOVE this project!
### what's not going well
I got paged 10 times last week
### team priorities
how does my work fit in with company goals?
### career planning
I'd like to be promoted this year
### ask for opportunities
I want to work on a customer-facing project
### ask for feedback
do you have any concerns about how PROJECT is going?
### brainstorm
let's think about this problem!
### give feedback
the team seems really unfocused recently
### ask for resources
I think this training would really help me</div>
|
|
| /comics/brackets-cheatsheet/ |
<span class="title">
bash brackets cheat sheet
</span>
<div class="keywords">[bash]</div>
<div class="transcript">### shell scripts have a lot of brackets
here's a cheat sheet to help you identify them all! we'll cover the details later.
### (cd ~/music; pwd)
`(...)` runs commands in a subshell.
### VAR=$(cat file.txt)
`$(COMMAND)` is equal to `COMMAND`'S stdout
### { cd ~/music; pwd; }
`(...)` groups commands. runs in the same process.
### x=(1 2 3)
`x=(...)` creates an array
### x=$((2+2))
`$(())` does arithmetic
### if [...]
`/usr/bin/[` is a program that evaluates statements
### <(COMMAND)
"process substitution": an alternative to pipes
### a{.png, .svg}
this expands to `a.png a.svg` it's called "brace expansion"
### if [[ ... ]]
`[[` is bash syntax. it's more powerful than `[`
### ${var//search/replace}
see page 21 for more about `${...}`!</div>
|
|
| /comics/box-model/ |
<span class="title">
the box model
</span>
<div class="keywords"></div>
<div class="transcript">### every HTML element is in a box
```
<div class="1">
<div class="2" />
<div class="3" />
</div>
```
Illustration of a larger box, labelled 1. Nested inside it are two boxes. The one on top is labelled 2, and the one below 2 is labelled 3.
### boxes have padding, borders, and a margin
Illustration of a series of nested boxes. The middle box is empty. The area around the middle box is labelled "padding". The area around the padding is labelled "border". The area around the border is labelled "margin".
### width & height don't include any of those
The same illustration from the previous panel, but with two lines measuring the width and height of only the middle box, not the padding, border, or margin.
### margins are allowed to overlap sometimes
Illustration of two sets of nested boxes, similar to the diagrams above. One is on top of the other, and the area between the sets of boxes is shaded in green, showing that the bottom margin of the first set of boxes, and the top margin of the second set of boxes, overlap.
the browser combines these top/bottom margins.
look up "margin collapse" to learn more
### `box-sizing: border-box;` includes border + padding in the width/height
Illustration of a series of nested boxes with a middle box surrounded by padding, border, and margin. In this version, the lines measuring width and height extend all the way to the edge of the border (but don't include the margin surrounding the border.)
### inline elements ignore other inline elements' vertical padding
Illustration of two dotted line boxes stacked directly on top of one another. Each has the word "`span`" inside it.
you can set vertical padding but the other span won't move</div>
|
|
| /comics/memory-allocation/ |
<span class="title">
memory allocation
</span>
<div class="keywords"></div>
<div class="transcript">### your program has memory
10MB: program binary
3MB: stack
587 MB: heap
the heap is what your allocator manages
### Your memory allocator (malloc) is responsible for 2 things.
THING 1: keep track of what memory is used/free.
### THING 2: Ask the OS for more memory!
malloc: oh no! I'm being asked for 40 MB and I don't have it.
malloc: can I have 60 MB more?
OS: here you go!
### your memory allocator's interface
- malloc(size_t size): allocate size bytes of memory & return a pointer to it.
- free (void* pointer): mark the memory as unused (and maybe give back to the OS)
- realloc(void pointer, size_t size): ask for more/less memory for pointer.
- Calloc (size-t members, size_t size): allocate array + initialize to 0.
### malloc tries to fill in for space memory when you ask
your code: can I have 512 bytes of memory?
malloc: YES!
### malloc isn't magic! it's just a function!
you can always:
- use a different malloc library like jemalloc or tcmalloc (easy!)
- implement your own malloc (harder)</div>
|
|
| /comics/misc-commands/ |
<span class="title">
misc commands
</span>
<div class="keywords"></div>
<div class="transcript">### `rlwrap`
adds history & ctrl support to REPLs that don't already have them
(`rl` stands for readline)
`$ rlwrap python`
### `watch`
rerun a command every 2 second
### `file`
figures out what kind of file (png? pdf?) a file is
### `pv`
"pipe viewer", gives you stats on data going through a pipe
### `cal`
a tiny calendar (heart)
### `ts`
add a timestamp in front of every input line
### `comm`
find lines 2 sorted files have in common
### `ncdu`
figure out what's using all your disk space
### `column`
format input into columns
### `diff`
diff 2 files. Run with `-U 8` for context.
### `xsel/xclip`
copy/paste from system clipboard
(`pbcopy`/`pbpaste` on Mac)</div>
|
|
| /comics/sql-query-order/ |
<span class="title">
SELECT queries start with FROM
</span>
<div class="keywords"></div>
<div class="transcript">Conceptually, every step (like "`WHERE`") of a query transforms its input, like this:
cats
owner: 1 name: daisy
owner: 1 name: dragonsnap
owner: 3 name: buttercup
owner: 4 name: rose
`WHERE owner = 1`
owner: 1 name: daisy
owner: 1 name: dragonsnap
The query's steps don't happen in the order they're written:
how the query' is written
SELECT...
FROM + JOIN
WHERE ...
GROUP BY ...
HAVING ...
ORDER BY...
LIMIT...
how you should think about it:
FROM + JOIN
↓
WHERE
↓
GROUP BY
↓
HAVING
↓
SELECT
↓
ORDER BY
↓
LIMIT
(In reality query execution is much more complicated than this. There are a lot of optimizations.)</div>
|
|
| /comics/request-headers/ |
<span class="title">
the most important HTTP request headers
</span>
<div class="keywords"></div>
<div class="transcript">These are the most important request headers:
### Host
The domain
The only required header.
`Host: examplecat.com`
### User-Agent
name + version of your browser and OS
`User-Agent: curl 7.0.2`
### Referer
(yes, it's misspelled!)
website that linked or included the resource
`Referer: http://examplecat.com`
### Authorization
eg a password or API token
base64 encoded user: password
`Authorization: Basic YXZ`
### Cookie
send cookies the server sent you earlier
keeps you logged in
`Cookie: user=b0rk`
### Range
lets you continue downlats ("get bytes 100-200")
`Range: bytes=100-200`
### Cache-Control
"max-age=60"
means cached responses must be less than 60 seconds old
### If-Modified-Since
only send if resource was modified after this time
`If-Modified-Since: Wed, 21 Oct...`
### If-None-Match
only send if the ETag doesn't match those listed
`If-None-Match: "e7ddac"`
### Accept
MIME type you want the response to be
`Accept: image/png`
### Accept-Encoding
set this to "gzip" and you'll probably get a compressed response"
`Accept-Encoding: gzip`
### Accept-Language
set this to "fr-CA" and you might get a response in French
`Accept-Languag: fr-CA`
### Content-Type
MIME type of request body, e.g. "application/json"
### Content-Encoding
will be "gzip" if the request body is gzipped
### Connection
"close" or "keep-alive".
Whether to keep the TCP connection open</div>
|
|
| /comics/curl/ |
<span class="title">
curl
</span>
<div class="keywords"></div>
<div class="transcript">### `curl`
smiling stick figure with short curly hair: it's my favourite way to make HTTP requests!
great for testing APIs!
`$ curl wizardzines.com`
### `-H`
is for for header
good for POST requests to JSON APIs
`-H` "content-Type:application/json"
allow compressed response:
`-H` "Accept-Encoding: gzip"
### `-L`
follow 3xx redirects
### `--data`
`--data '{"name": "julia"'`
`--data @filename.json`
(@ reads the data to send from a file)
### `i`
show response headers
### `I`
show ONLY response headers (makes a HEAD request)
### `- X POST`
send a POST request instead of a GET (`-X PUT` etc works too)
### `- v`
show request headers & more
### `- k`
insecure: don't verify SSL certificates
### `--connect to ::IP`
(or hostname)
send request to IP instead
use bfore changing DNS to a new IP
### `copy as cURL`
Have something in your browser you want to download from the command line?
In Firefox/Chrome/Safari:
Developer Tools
-> Network tab
-> right click on the request
-> copy as curl
(can have sensitive info in cookies!)</div>
|
|
| /comics/bash-errors/ |
<span class="title">
bash errors
</span>
<div class="keywords"></div>
<div class="transcript">### by default, bash will continue after errors
bash, represented by a box with a smiley face: oh, was that an error? who cares, let's keep running!!!
programmer, represented by a nonplussed stick figure with short curly hair: uh that is NOT what I wanted
### `set -e` stops the script on errors
```
set -e
unzip fle.zip
```
(typo! script stops here!)
programmer, smiling: this makes your scripts WAY more predictable
### by default, unset variables don't error
`rm -r "$HOME/$SOMEPTH"`
bash, happily: `$SOMEPTH` doesn't exist? no problem, i'll just use an empty string!
programmer: OH NOOOO that means `rm -rf $HOME`
### `set -u` stops the script on unset variables
```
set-u
rm -r "$HOME/$SOMEPTH"
```
bash, concerned: I've never heard of `$SOMEPTH`! STOP EVERYTHING!!!
### by default, a command failing doesn't fail the whole pipeline
`curl yxqzq.ca | grep 'panda'`
bash, pleased with itself: `curl` failed but `grep` succeeded so it's fine! success!
### `set -o pipefail` makes the pipe fail if any command fails
you can combine `set -e`, `set -u`, and `set -o pipefail` into one command I put at the top of all my scripts:
`set -euo pipefail`</div>
|
|
| /comics/xargs/ |
<span class="title">
xargs
</span>
<div class="keywords"></div>
<div class="transcript">### xargs takes white space separated strings from stdin and converts them into command-line arguments
```
$ echo "/home /tmp"
| xargs ls
```
will run `ls /home/tmp`
### this is useful when you want to run the same command on a list of files!
- delete (`xargs rm`)
- combine (`xargs cat`)
- search (`xargs grep`)
- replace (`xargs sed`)
### how to replace "foo" with "bar" in all .txt files:
```
find. -name '*.txt' |
xargs sed -i s/foo/bar/g
```
### how to lint every Python file in your Git repo:
```
git ls-files | grep pyl
xargs pep8
```
### if there are spaces in your filenames "my day.txt" xargs will think it's 2 files
""my" and "day.txt"
fix it like this:
```
find -print0 |
xargs -0 COMMAND
```
### more useful xargs options
`-n 1` (max-args): makes xargs run a separate process max-args for each input
`-P` (capital P, max-procs): is the max number of parallel processes xargs will start</div>
|
|
| /comics/awk/ |
<span class="title">
awk
</span>
<div class="keywords"></div>
<div class="transcript">### panel 1:
awk is a tiny programming language for manipulating columns of data
person: I only know how to do 2 things with awk but it's still useful!
### panel 2: basic awk program structure
```
BEGIN {...}
CONDITION (action}
CONDITION (action}
```
(do action on lines matching CONDITION)
```
END {...}
```
### panel 3: extract a column.of text with awk
```awk -F, '{print $5}'```
the comma is the column separator
the ' is a single quote!
```{print $5}``` means print the 5th column
person: this is 99% of what I do with awk
### panel 4:
SO MANY Unix commands print columns of text (ps! Is!)
so being able to get the column you want with awk is GREAT
### panel 5: awk program example
sum the numbers in the 3rd column
``` {s += $3};``` (action)
``` END {print s}'``` (at the end, print the sum!)
### panel 6: awk program example
print every line over 80 characters
```length($0) > 80```
"length" is the condition
(there's an implicit ```{print}``` as the action)</div>
|
|
| /comics/cors/ |
<span class="title">
CORS
</span>
<div class="keywords"></div>
<div class="transcript">cross-origin resource sharing
Cross-origin requests are not allowed by default: (because of the same origin policy!)
Javascript from clothes.com: POST request to api.clothes.com?
Firefox (thought bubble): same origin flow chart
Firefox: NOPE. api.clothes.com is a different origin from clothes.com
If you run api.clothes.com, you can allow clothes.com to make requests to it using the `Access-Control-Allow-Origin` header. Here's what happens:
javascript on clothes.com: `POST /buy_thing`\
`Host: api.clothes.com`
Firefox (thought bubble): That's cross-origin. I'm going to need to ask api.clothes.com if this request is allowed.
Firefox: `OPTIONS /buy_thing`\
`Host: api.clothes.com` ("hey, what requests are allowed?" preflight request)
api.clothes.com: ```204 No Content`` ```Access-Control-Allow-Origin: clothes.com`
Firefox (thought bubble): cool, the request is allowed!
Firefox: `POST /buy_thing`\
`Host: api.clothes.com`\
`Referer: clothes.com/checkout`
api.clothes.com: `200 OK`\
`{"thing_bought": true}`
This OPTIONS request is called a "preflight" request, and it only happens for some requests, like we described in the diagram on the same-origin policy page. Most GET requests will just be sent by the browser without a preflight request first, but POST requests that send JSON need a preflight.</div>
|
|
| /comics/css-variables/ |
<span class="title">
CSS variables
</span>
<div class="keywords"></div>
<div class="transcript">### duplication is annoying
Illustration of a frowning stick figure with curly hair.
person, thinking: ugh, I have `color: #f79` set in 27 places and now I need to change it in 27 places
### define variables in any selector
```
body {
--text-color: #f79;
body {
}
```
(applies to everything)
```
#header {
--text-color: #c50;
}
```
(applies to children of `#header`)
### use variables with `var()`
```
body {
color: var(--text-color);
}
```
(variables always start with `--`)
### do math on them with `calc()`
```
#sidebar {
width: calc(
var (--my-var) + 1em
);
}
```
### you can change a variable's value in Javascript
```
let root =
document.documentElement;
root.style.setProperty(
'--text-color', 'black');
```
### changes to variables apply immediately
JS, represented by a box with a smiley face: set `--text-color` to red
css renderer, also represented by a box with a smiley face: ok everything using it is red now!
</div>
|
|
| /comics/containers-arent-magic/ |
<span class="title">
containers aren't magic
</span>
<div class="keywords"></div>
<div class="transcript">These 15 lines of bash will start a container running the fish shell. Try it! (download this script at bit.ly/containers-arent-magic)
It only runs on Linux because these features are all Linux-only.
`wget bit.ly/fish-container -O fish.tar` (# 1. download the image)
`mkdir container-root; cd container-root`
`tar -xf ../fish.tar` (# 2. unpack image into a directory)
`cgroup_id="cgroup_$(shuf -i 1000-2000 -n 1)"` (# 3. generate random cgroup name)
`cgcreate -g "cpu, cpuacct, memory: $cgroup_id"` (# 4. make a cgroup & set CPU/memory limits)
`cgset -r cpu. shares=512 "$cgroup_id"`
`cgset -r memory.limit_in_bytes=1000000000 \`
`"$cgroup_id"`
`cgexec -g "cpu, cpuacct, memory: $cgroup_id" \ ` (# 5. use the cgroup)
`unshare -fmuipn --mount-proc\` (# 6. make and use some namespaces)
` chroot "$PWD" \` (# 7. change root directory)
`/bin/sh -c "`
`/bin/mount -t proc proc /proc &&` (# 8. use the right /proc)
`hostname container-fun-times &&` (# 9. change the hostname)
`/usr/bin/fish"` (# 10. finally, start fish!)</div>
|
|
| /comics/virtual-memory/ |
<span class="title">
virtual memory
</span>
<div class="keywords"></div>
<div class="transcript">### your computer has physical memory
memory
868 204-PIN SODIMM DDR3 CE
### physical memory has addresses, like O-8GB
but when your program references an address like Ox 5c69a2a2, that's not a physical with memory address! It's a virtual address.
### every program has its own virtual address space
program 1: Ox 129520 → "puppies"
program 2: Ox 129520 → "bananas"
### Linux keeps a mapping, from virtual memory pages to physical memory pages called the page table
a "page" is a 4kb or chunk of memory (or sometimes bigger)
PID -- virtual addr -- physical addr
1971 -- Ox 20000 -- Ox 192000
2310 -- Ox 20000 -- Ox 228000
2310 -- Ox21000 -- Ox 9788000
### when your program accesses a virtual address
CPU: I'm accessing Ox21000
MMU "memory management unit" (hardware): I'll look that up in the page table and then access the right physical address
### every time you switch which process is running, Linux needs to switch the page table
Linux: here's the address of process 2950's page table
MMU: thanks, I'll use that now!</div>
|
|
| /comics/syscalls/ |
<span class="title">
how to talk to your operating system
</span>
<div class="keywords"></div>
<div class="transcript">## how to talk to your operating system
### WRONG:
weird guy: good morning madam would you care to open a file for me
operating system: what
### RIGHT:
system calls! yay! (surrounded by hearts, smiley faces, and exclamation marks)
happy stick figure with curly hair:
```
open("/cool.txt")
connect(<my friend's computer>)
```
your programs can:
- open
- read
- write
files
talk to other computers with networking:
- connect
- sendto
- recvfrom
start other programs:
- execue
AND MUCH MORE!!!
(these are all system calls on Linux!)</div>
|
|
| /comics/cdn/ |
<span class="title">
content delivery networks
</span>
<div class="keywords"></div>
<div class="transcript">In 2004, if your website suddenly got popular, often the webserver wouldn't be able to handle all the requests.
slashdot:
person 1: I want cat picture!
person 2: me too!
person 3: me 300,000!
server, on fire: <no response>
web host: now you owe me $1000 for bandwidth
you: how will I pay for this?
A CDN (content delivery network) can make your site faster and save you money by caching your site and handling most requests itself.
20 million requests for 1 cute cat picture -> CDN (many powerful computers) ->
just 1 request: hey send me that cat picture?
server: here you go!
Today, there are many free or cheap CDN services available, which means if your site gets popular suddenly you can easily keep it running!
This is great but caching can cause problems too!
I updated my site yesterday but people are still seeing the old site!
(Cache-Control header)
French users are seeing the English site?!? Why?
(Vary header)
Next, we'll explain the HTTP headers your CDN or browser uses to decide how to do caching.</div>
|
|
| /comics/ask-for-specific-feedback/ |
<span class="title">
ask for specific feedback
</span>
<div class="keywords">[manager]</div>
<div class="transcript">I used to ask for feedback like this:
Illustration of two stick figures, both smiling. Person 1, the employee, has short curly hair, and person 2, the manager, doesn't have hair.
person 1 (speech bubble): dо you have any feedback for me?
person 2 (speech bubble): not right now!
person 1 (thought bubble): is there something they're not telling me?
person 2 (thought bubble): what specifically does she want feed back on?
I've learned that I get WAY BETTER answers if I ask more specific questions!
- what do you think of this design?
- did I prioritize these things well?
- should I be doing more or less of X?
- do you have any concerns about PROJECT?
- was that email clear?
Bonus: asking specific questions forces me to actually think about which areas I might want to focus on.</div>
|
|
| /comics/ip/ |
<span class="title">
ip
</span>
<div class="keywords"></div>
<div class="transcript">### ip
(Linux only)
lets you view + change network configuration.
`ip OBJECT COMMAND`
(`OBJECT` = addr, link neigh, etc)
(`COMMAND` = add, show, delete, etc)
Here are some ways to use it!
### ip addr list
shows ip addresses your devices. Look for something like this:
```
2: eth0:
link/ether 3c:97...
inet 192.168.1.170/24
```
### ip route list
displays the route table.
`default via 192.168.1.1` (my router)
`169.240.0.0/16 dev docker`
`...`
to see all route tables:
`ip route list table all`
### change your MAC address
good for cafés with time limits (devil face emoji)
```
$ ip link set wlan0 down
$ ip link set wlan0 address
3ca9f4d1:00:32
$ ip link set wlan0 up
$ service network-manager
restart
```
(or whatever you use)
### `ip link`
network devices! (like eth0)
### `ip neigh`
view/edit the ARP table
### `ip xfrm`
is for IPsec
### `ip route get IP`
what route will packets with $IP take?
### `--color`
(the letters of "color" are in various rainbow colours)
pretty colourful output!
### `-- brief`
show a summary
</div>
|
|
| /comics/how-urls-work/ |
<span class="title">
how URLs work
</span>
<div class="keywords"></div>
<div class="transcript">`https://examplecat.com:443/cats?color=light%20gray#banana`
- scheme (`https://`): Protocol to use for the request. Encrypted (`https`), insecure (`http`), or something else entirely (`ftp`).
- domain (`examplecat.com`): Where to send the request. For HTTP(s) requests, the Host header gets set to this (`Host: example.com`)
- port (`:443`): Defaults to 80 for HTTP and 443 for HTTPS.
- path (`/cats`): Path to ask the server for. The path and the query parameters are combined in the request, like: `GET /cats?color=light%20gray HTTP/1/1`
- query parameters (`color=light gray`): Query parameters are usually used to ask for a different version of a page ("I want a light gray cat!"). Example:
`hair-short&color=black&name=mr%20darcy`. Hair is the name, short is the value, separated by &
- URL (`encoding %20`): URLS aren't allowed to have certain special characters like spaces, @, etc. So to put them in a URL you need to percent encode them as % + hex representation of ASCII value. space is %20, % is %25, etc.
- fragment id (`#banana`): This isn't sent to the server at all. It's used either to jump to an HTML tag (`<a id="banana"..>`) or by Javascript on the page.
</div>
|
|
| /comics/namespaces/ |
<span class="title">
namespaces
</span>
<div class="keywords">[containers]</div>
<div class="transcript">### inside a container, things look different2`
Illustration of a smiling stick figure with curly hair.
Person: I only see 4 processes in `ps aux`, that's weird...
### why things look different: namespaces
Illustration of a container, represented by a box with a smiley face
Container: I'm in a different PID namespace so `ps aux` shows different processes!
### every process has 7 namespaces
```
$ lsns -p 273
NS TYPE
4026531835 cgroup
4026531836 pid
4026531837 user
4026531838 uts
4026531839 ipc
4026531840 mnt
4026532009 net
```
-p is the PID
4026532009 is the namespace ID
you can also see a process's namespace with:
`$ ls -1 /proc/273/ns`
### there's a default ("host" namespace)
Person: "outside a container" just means "using the default namespace"
### processes can have any combination
Container: I'm using the host network namespace but my own mount container namespace!</div>
|
|
| /comics/units/ |
<span class="title">
CSS units
</span>
<div class="keywords"></div>
<div class="transcript">### CSS has 2 kinds of units: absolute & relative
absolute:
- px
- pt
- pc
- in
- cm
- mm
relative
- em
- rem
- vw
- vh
- %
### `rem`
the root element's font size
`1rem` is the same everywhere in the document. `rem` is a good unit for setting font sizes!
### `em`
the parent element's font size
```
.child {
font-size: 1.5em;
}
```
Illustration of a box labelled "parent". Inside it is a box labelled, in larger text, "child". An arrow is pointing to the "child" text, labelled "font size is 1.5 x parent".
### O is the same in all units
```
.btn {
margin: 0;
}
```
also, `0` is different from `none`. `border: 0` sets the border width and `border: none` sets the style
### 1 inch = 96 px
on a screen, 1 CSS "inch" isn't really an inch, and 1 CSS "pixel" isn't really a screen pixel. look up "device pixel ratio" for more.
### rem & em help with accessibility
```
.modal {
width: 20rem;
}
```
this scales nicely if the user increases their browser's default font size</div>
|
|
| /comics/css-centering/ |
<span class="title">
centering in CSS
</span>
<div class="keywords"></div>
<div class="transcript">### center text with `text-align`
```
h2 {
text-align: center;
}
```
### center block elements with `margin: auto`
example HTML:
```
<div class="parent">
<div class="child">
</div>
</div>
```
### `margin: auto` only centers horizontally
```
.child {
width: 400px;
margin: auto;
}
```
Illustration of a smaller box, labelled "child", inside a larger box. The child box is at the top of the larger (parent) box. An arrow pointing to the child box is labelled "not centered vertically!"
### vertical centering is easy with flexbox or grid
A spiky box labelled "TRY ME"
here's how with grid:
```
.parent {
display: grid;
place-items: center;
}
```
and with flexbox:
```
.parent {
display: flex;
}
.child {
margin: auto;
}
```
### it's ok to use a flexbox or grid just to center one thing
Illustration of a smaller box nested inside a larger box. The larger box is labelled ".parent `(display: grid)`" and the smaller box is labelled ".child (centered!)"</div>
|
|
| /comics/less/ |
<span class="title">
less
</span>
<div class="keywords"></div>
<div class="transcript">### less is a pager
that means it lets you view (not edit) text files.
man uses your pager (usually `less`) to display man pages
### many vim shortcuts work in less
- `/` search
- `n/N` next/prev match
- `j/k` down / up a line
- `m/'` mark/return to line
- `g`(`gg` in vim)/`G` beginning /end of file
### less -r
displays bash escape codes as colours
try `ls --color | less -r`
with `-r`:
- `a.txt`
- `a.txt.gz` (red, bold)
without `-r`
- `a.txt`
ESCLOM ESC C01;31ma.txt.gz ESCCOM
(ugh)
or piped in text
### q
quit (smiley face)
### v (lowercase)
edit file in your $EDITOR
### arrow keys, Home / End, PgUp, Pg Dn work in less
### F
press F to keep reading from the file as it's updated (like `tail -f`)
press Ctrl+C to stop reading updates
### +
`+` runs a command when less starts
- `less +F` : follow updates
- `less +G`: start at end of file
- `less +20%`: start 20% into file
- `less +/foo`: search for 'foo' right away</div>
|
|
| /comics/netcat/ |
<span class="title">
netcat
</span>
<div class="keywords"></div>
<div class="transcript">### `nc`
lets you create TCP (or UDP) connections from the command line
smiling stick figure, to box with smiley face: I hand wrote this HTTP request for you!
### `nc - l PORT`
start a server! this listens on `PORT` and prints everything received
network connection -> `nc` -> `stdout`
### `nc IP PORT`
be a client! opens a TCP connection to `IP:PORT` (to send UDP use `-u`)
### `make HTTP request by hand`
```
printf 'GET / HTTP/ 1.1\r\nHost:example.com\r\n\r\n' | nc example.com 80
```
type in any weird HTTP request you want! (smiley face)
### `send files`
want to send a 100GB file to someone on the same wifi network? easy!
```
receiver:
nc-1 8000 > file
sender:
cat file | nc YOUR_IP 8080
```
happy stick figure with short curly hair: I love this trick It works even if you're disconnected from the internet!</div>
|
|
| /comics/having/ |
<span class="title">
HAVING
</span>
<div class="keywords"></div>
<div class="transcript">person: every user has a different email right?
1 query later... person, now sad: oh no
This query uses `HAVING` to find all emails that are shared by more than one user:
```
SELECT email, COUNT(*)
FROM users
GROUP BY email
HAVING COUNT(*) > 1
```
users:
id 1, email asdf@fake.com
id 2, email bob@builder.com
id 3, email asdf@fake.com
query output:
email asdf@fake.com, `COUNT`(*) 2
`HAVING` is like `WHERE`, but with 1 difference: `HAVING` filters rows AFTER grouping and `WHERE` filters rows BEFORE grouping.
Because of this, you can use aggregates (like `COUNT` (*)) in a `HAVING` clause but not with `WHERE`.
Here's another `HAVING` example that finds months with more than $6.00 in income:
```
SELECT month
FROM sales
GROUP BY month
HAVING SUM(price) > 6
```
sales:
month: Jan. item: catnip price: 5
month: Feb item: laser price: 8
month: March item: food price: 4
month: March item: food price: 3
query output:
month: Feb
month: March</div>
|
|
| /comics/sed/ |
<span class="title">
sed
</span>
<div class="keywords"></div>
<div class="transcript">### sed is most often used for replacing text in a file
`$ sed s/cat/dog/g file.txt`
"cat"can be a regular expression
### change a file in place. with -i
person: in GNU sed it's -i, in BSD sed, -i SUFFIX confuses me every time.
### Some more sed incantations...
### sed -n 12 p
print 12th line
-n suppresses output so only what you print with 'p' gets printed
### sed 5 d
delete 5th line
### sed /cat/d
delete lines matching /cat/
### sed -n 5,30 p
print lines 5-30
### sed s+cat/+dog/+
('+' can be any character)
Use + as a regex delimeter
person: way easier than escaping /s like s/cat\//dog\//!
### sed -n s/cat/dog/p
only print changed lines.
### sed G
double space a file (good for long error lines)
### sed /cat la dog'
append 'dog' after lines containing 'cat'
### sed 'i 17 panda"
insert "panda" on line 17</div>
|
|
| /comics/write-for-one-person/ |
<span class="title">
write for one person
</span>
<div class="keywords"></div>
<div class="transcript"></div>
|
|
| /comics/ngrep/ |
<span class="title">
ngrep
</span>
<div class="keywords">[tcpdump]</div>
<div class="transcript">### like grep for your network
(network is surrounded with glowy lines)
`$ sudo ngrep GET` will find every plaintext HTTP GET request
### ngrep syntax
```
$ ngrep
[options]
[regular expression]
[BPF filter]
```
("regular expression" is what to search packets for)
"BPF filter" use the same format as tcpdump uses!
### panel 3
Illustration of a smiling stick figure with curly hair.
person: I started using `ngrep` when I was intimidated by tcpdump and I found it easier (heart)
### -d
is for device
which network interface to use. same as tcpdump's `-i` (try `-d any`!)
ngrep
### -W byline
prints line breaks as line breaks, not "\n". Nice when looking at HTTP requests
### -I file.pcap -O file.pcap
read/write packets from/to a pcap file</div>
|
|
| /comics/disk-usage/ |
<span class="title">
du & df
</span>
<div class="keywords"></div>
<div class="transcript"></div>
|
|
| /comics/floating-point/ |
<span class="title">
floating point
</span>
<div class="keywords"></div>
<div class="transcript">### a double is 64 bits
```
10011011 10011011 10011011 1011011
10011011 10011011 10011011 1011011
```
(the first digit is the sign, the next 11 digits are the exponent, the rest is the fraction)
± 2 ^ E - 1023 x 1.frac
That means there are 2^64 doubles.
The biggest one is about 2^1023
### weird double arithmetic
2^52 + 0.2 = 2^52 (the next number after 2^52 is 2^52 + 1)
### doubles get farther apart as they get bigger
betweeen 2^n and 2^n+1 there are always 2^52 doubles, evenly spaced
that means that the next double after 2^60 is 2^60 =64 (2^60 / 2^52)
### Javascript *only* has doubles (no integers!)
> 2**53
9007199254740992
> 2**53+1
9007199254740992 (same number! uh oh!)
### panel 5
person with short spiky hair, baffled: doubles are scary and their arithmetic is weird!
person with short curly hair, calm and reassuring: they're very logical! just understand how they work and don't use integers over 2^53 in Javascript <3</div>
|
|
| /comics/cgroups/ |
<span class="title">
cgroups
</span>
<div class="keywords">[containers]</div>
<div class="transcript">### processes can use a lot of memory
process 1: I want 10 GB of memory
process 2: me too!
Linux: guys, I only have 16 GB total
### a cgroup is a group of processes
every process in a container is in the same cgroup
### cgroups have memory/CPU limits
Linux: you three get 500 MB of RAM to share, okay?
### use too much memory:| get OOM ("out of memory") killed
process: I want 1 GB of memory
Linux: NOPE your limit was 500 MB you die now!
process, dead: oh no
### use too much CPU: get slowed down
process: I want to use ALL THE CPU!
Linux: you hit your quota for this 100ms period, you'll have to wait
### cgroups track memory & CPU usage
Linux: that cgroup is using 112.3 MB of memory right now
you can see it in `/sys/fs/cgroup`</div>
|
|
| /comics/shared-libraries/ |
<span class="title">
shared libraries
</span>
<div class="keywords"></div>
<div class="transcript">### panel 1:
Most programs on Linux use a bunch of C libraries.
Some popular libraries:
openssl (for SSL!)
sqlite (embedded db?)
zlib (gzip!)
lib pcre (regular expressions!)
libstdc++ (C++ standard library!)
### panel 2:
There are 2 ways. to use any library:
1. Link it into your binary
your code (big binary with lots of things!) | zlib | sqlite
and
2. Use separate shared libraries
your code
zlib
sqlite
(all different files)
### panel 3:
Programs like this
your code | zlib | sqlite
are called "statically linked"
programs like this
your code
zlib
sqlite
are called "dynamically linked"
### panel 4:
person 1: how can I tell what shared libraries a Program is using?
person 2: Idd!!
```$ Idd /usr/bin/curl
libz.so.1 => /lib/x86-64...
lib resolv.so.2 =>....
libc.so.6 =>...
```
+34 more
### panel 5:
person 1: I got a "library not found" error when running my binary?!
person 2: If you know where the library is, try setting the ```LD_LIBRARY_PATH``` environment variable
dynamic linker: ```LO-LIBRARY_PATH``` tells me where to look!
### panel 6: Where the dynamic linker looks
1. ```ODT. RPATH``` in your executable
2. ```LD- LIBRARY_PATH```
3. ```DT- RUNPATH``` in executable
4. ```/etc/ld.so.cache.```
(run ```Idconfig -p``` to See contents)
5. ```/lib, /usr/lib```</div>
|
|
| /comics/take-on-hard-projects/ |
<span class="title">
take on hard projects
</span>
<div class="keywords"></div>
<div class="transcript">To wrap up, let's talk about one last wizard skill: confidence. When there's a hard project, sometimes I think:
maybe someone better than me should work on this?
and I imagine this magical human:
- codes really fast
- knows everything about every technology
- understands the business well
- great communicator
- has time for the project
- 20 years of experience
But in programming:
- we're changing the tech we use all the time.
- every project is different, and it's rarely obvious how to do it.
- there aren't many experts, and they certainly don't have time to do everything.
So instead, we have me:
- learns fast
- works hard
- 6 years of experience
- good at debugging
I figure "someone's gotta do this' write down a plan, and get started! A lot of the time, it turns out well. I learn something and feel a little more like a WIZARD.</div>
|
|
| /comics/anatomy-http-response/ |
<span class="title">
anatomy of a HTTP response
</span>
<div class="keywords"></div>
<div class="transcript">### HTTP responses have:
- a status code (200 OK! 404 not found!)
- headers
- a body (HTML, an image, JSON, etc)
### Here's the HTTP response from `examplecat.com/cat.txt`:
```
HTTP/1.1 200 OK
status
Accept-Ranges: bytes
Cache-Control: public, max-age=0
Content-Length: 33
Content-Type: text/plain; charset=UTF-8 Date: Mon, 09 Sep 2019 01:57:35 GMT
Etag: "ac5affa59f554a1440043537ae973790-ssl"
Strict-Transport-Security: max-age=31536000
Age: 0
Server: Netlify
[ASCII image of a cat, labelled "cat!" with a smiley face]
```
The first line, `HTTP/1.1 200 OK` is the status code. "200" is the status.
The lines from `Accept-Ranges` to `Server` are the headers.
The cat picture is the body.
### There are a few kinds of response headers:
- when the resource was sent/modified:
```
Date: Mon, 09 Sep 2019 01:57:35 GMT
Last-Modified: 3 Feb 2017 13:00:00 GMT
```
- about the response body:
```
Content-Language: en-US
Content-Length: 33
Content-Type: text/plain; charset=UTF-8
Content-Encoding: gzip
```
- caching:
```
ETag: "ac5affa..."
Vary: Accept-Encoding
Age: 255
Cache-Control: public, max-age=0
```
- security: (see page 25)
```
X-Frame-Options: DENY
X-XSS-Protection: 1
Strict-Transport-Security: max-age=31536000
Content-Security-Policy: default-src https:
```
- and more:
```
Connection: keep-alive
Accept-Ranges: bytes
Via: nginx
Set-Cookie: cat-darcy; HttpOnly; expires=27-Feb-2020 13:18:57 GMT;
```</div>
|
|
| /comics/anatomy-http-request/ |
<span class="title">
anatomy of a http request
</span>
<div class="keywords"></div>
<div class="transcript">HTTP requests always have:
- a domain (like `examplecat.com`)
- a resource (like `/cat.png`)
- a method (`GET`, `POST`, or something else)
- headers (extra information for the server)
There's an optional request body. `GET` requests usually don't have a body, and `POST` requests usually do.
This is an HTTP 1.1 request for `examplecat.com/cat.png`. It's a `GET` request, which is what happens when you type a URL in your browser. It doesn't have a body.
```
GET /cat.png HTTP/1.1
Host: examplecat.com
User-Agent: Mozilla...
Cookie: .....
```
`GET` = method (usually GET or POST)
`/cat.png` = resource being requested
`HTTP/1.1` = HTTP version
`examplecat.com` = domain being requested, header
`User-Agent: Mozilla`... = header
`Cookie: .....` = header
Here's an example POST request with a JSON body:
```
POST /add_cat HTTP/1.1
Host: examplecat.com
content type of body
Content-Type: application/json
Content-Length: 20
```
{"name": "mr darcy"}
`POST` = method
`Host: examplecat.com` = header
`Content-Type: application/json` = content type of body, header
`Content-Length: 20` = header
`{"name": "mr darcy"}` = request body: the JSON we're the server sending to</div>
|
|
| /comics/why-containers/ |
<span class="title">
why containers?
</span>
<div class="keywords"></div>
<div class="transcript">### there's a lot of container hype
Illustration of two stick figures with medium-length straight hair. One has hearts in their eyes and a speech bubble that says "containers" with hearts around it, the other one has a thought bubble that says "???"
Here are 2 problems they solve...
### problem: building software is annoying
```
$ ./configure
$ make all
ERROR: you have version
2.1.1 and you need
at least 2.2.4
```
### solution: package all dependencies in a * container *
stick figure with medium length straight hair and bangs, thinking: I ran the container and the build worked RIGHT AWAY?? is that allowed??
Many CI systems use containers.
### containers have their own filesystem
This is the big reason containers are great.
host OS, represented by a box with a smiley face: I'm running Ubuntu 19.04
container, also represented by a box with a smiley face: I'm running an old CentOS distribution host OS from 2014!
### problem: deploying software is annoying too
sad stick figure with short curly hair: ugh my website is broken because I used a Python 3.6 feature and the server only has Python 3.5
### solution: deploy a container
server: I have the exact same version of everything as in development! no more silly errors!
happy stick person with short curly hair: yay! I can get back to writing code!</div>
|
|
| /comics/dig/ |
<span class="title">
dig
</span>
<div class="keywords"></div>
<div class="transcript">### dig makes DNS queries!
```
$ dig google.com
```
answers have 5 parts:
- query: `google.com`
- TTL `22`
- clas: `IN` (for "internet", ignore this)
- record type: `A`
- record value: `172.217.13.110`
### dig TYPE domain.com
this lets you choose which DNS record to query for!
types to try:
- NS
- MX
- TXT
- CNAME
- A (default)
### dig @ 8.8.8.8 domain
(google DNS server)
dig@server lets you pick which DNS server to query. Useful when your system DNS is misbehaving :)
### dig + trace domain
traces how the domain gets resolved, starting at the root nameservers.
if you just updated DNS, dig + trace should show the new record.
### dig -x 172.217.13.174
makes a reverse DNS query -find which domain resolves to an IP! Same as `dig ptr 172.217.13.174.in.addr.arpa`
### dig +short domain
Usually dig pints lots of output! With +short it just prints the DNS record.</div>
|
|
| /comics/ps/ |
<span class="title">
ps
</span>
<div class="keywords"></div>
<div class="transcript"></div>
|
|
| /comics/joins/ |
<span class="title">
my rules for simple JOINs
</span>
<div class="keywords"></div>
<div class="transcript">my rules for simple `JOIN`s
Joins in SQL let you take 2 tables and combine them into one.
On the left side of the page, there is an illustration of two small tables with the words "INNER JOIN" between them. One has columns labelled a, b, c, and d, the other has columns labelled x, y, and z. On the right side of the page, there is a big table with columns a, b, c, d, x, y, and z.
Joins can get really complicated, so we'll start with the simplest way to join. Here are the rules I use for 90% of my joins:
#### Rule I: only use LEFT JOIN and INNER JOIN
There are other kinds of joins (`RIGHT JOIN`, `CROSS JOIN`, `FULL OUTER JOIN`), but of the time I only use `LEFT JOIN` and `INNER JOIN`.
#### Rule 2: refer to columns as `table_name.column_name`
You can leave out the table name if there's just one column with that name, but it can get confusing.
#### Rule 3: Only include 1 condition in your join
Here's the syntax for a LEFT JOIN:
```
table1 LEFT JOIN table2 ON <any boolean condition>
```
I usually stick to a very simple condition, like this:
```
table1 LEFT JOIN table2
ON table1.some_column = table2.other_column
```
#### Rule 4: One of the joined columns should have unique values
If neither of the columns is unique, you'll get strange results like this:
owners_bad:
| name | age |
|-------|-----|
| maher | 16 |
| maher | 32 |
| rishi | 21 |
`INNER JOIN`
cats_bad:
| name | age |
|-------|------------|
| maher | daisy |
| maher | dragonsnap |
| rishi | buttercup |
(these are "bad" versions of the "owners" and "cats" tables that don't `JOIN` well)
```
owners_bad INNER JOIN cats_bad
ON owners_bad.name = cats_bad.owner
```
| name | name | age |
|-------|------------|-----|
| maher | daisy | 16 |
| maher | dragonsnap | 16 |
| maher | daisy | 32 |
| maher | dragonsnap | 32 |
| rishi | buttercup | 21 |</div>
|
|
| /comics/status-codes/ |
<span class="title">
http status codes
</span>
<div class="keywords"></div>
<div class="transcript">Every HTTP response has a status code.
browser, optimistically: `GET /cat.png` (request)
server, sadly: 404 not found (404 is the status code!)
There are 50ish status codes but these are the most common ones in real life:
2xxs mean ★Success★
- 200 OK
3xx s aren't errors, just redirects to somewhere else
- 301 Moved Permanently
- 302 Found: temporary redirect
- 304 Not Modified: the client already has the latest version, "redirect" to that
4xx errors are generally the client's fault: it made some kind of invalid request
- 400 Bad Request
- 403 Forbidden: API key/OAuth/something needed
- 404 Not Found: we all know this one :)
- 429 Too Many Requests: you're being rate limited
5xx errors generally mean something's wrong with the server.
- 500 Internal Server Error: the server code has an error
- 503 Service Unavailable: could mean nginx (or whatever proxy) couldn't connect to the server
- 504 Gateway Timeout: the server was too slow to respond</div>
|
|
| /comics/sort-uniq/ |
<span class="title">
sort & uniq
</span>
<div class="keywords"></div>
<div class="transcript">### `sort` sorts its inputs
`$ sort name.txt`
the default sort is alphabetical
### `sort -n`: numeric sort
`sort order` (sad face):
- 12
- 15000
- 48
- 6020
- 96
`sort -n` order (happy face):
- 12
- 48
- 96
- 6020
- 15000
### `sort -h`: human sort
`sort -n` order (sad face):
- 15 G
- 30 M
- 45 K
- 200 G
`sort -h` order (happy face):
- 45 K
- 30 M
- 15 G
- 200 G
useful example: `du -sh * | sort -h`
### `uniq` removes duplicates
before:
- a
- b
- b
- a
- c
- c
after:
- a
- b
- a
- c
(notice there are still 2 'a's! uniq only uniquifies adjacent matching lines
### `sort` + `uniq` = (heart)
Pipe something to `sort | uniq` and you'll get a deduplicated list of lines! `sort -u` does the same thing.
before `sort -u` (or `sort | uniq`):
- b
- a
- b
- a
after:
- a
- b
### `uniq -c`
counts each line it saw.
Recipe: get the top 10 most common lines in a file:
```
$ sort foo.txt
| uniq -c
| sort -n
| tail -n 10
```
happy little stick figure with curly hair: I use this a lot!</div>
|
|
| /comics/indexes/ |
<span class="title">
how indexes make your queries fast
</span>
<div class="keywords"></div>
<div class="transcript">By default, if you run `SELECT * FROM cats WHERE name = 'mr darcy'` the database needs to look at every single row to find matches.
database, sad: reading 30 GB of data from disk takes like 60 seconds by itself, you know!
(at 500 MB/s SSD speed)
Indexes are a tree structure that makes it faster to find rows. Here's what an index on the 'name' column might look like.
a-z
aaron to ahmed
aaron to abdullah
agnes to ahmed
molly to nasir
60 children
waseem to zahra
database indexes are b-trees and the nodes have lots of children (like 60) instead of just 2.
log <sub>60</sub> (1,000,000,000) = 5.06
This means that if you have 1 billion names to look through, you'll only need to look at maybe nodes in the index to find the name you're looking for (5 is a lot less than 1 billion!!!).
person 1: are you saying indexes can make my queries 1,000,000x faster?
person 2: yes! actually some queries. on large tables are basically impossible (or would take weeks) without using an index!</div>
|
|
| /comics/ss/ |
<span class="title">
ss
</span>
<div class="keywords"></div>
<div class="transcript">### panel 1
two stick figures talking. the first one is bald and looks unhappy. the second one has short curly hair and is smiling.
person 1: I can't start my server because it says something is using port 8080!
person 2:
1. Use ss ("socket statistics") to find the process ID using the port
2. Kill the other process!
### * tuna, please! *
`$ ss -tunapl`
(the 'a' here doesn't do anything)
This is my favourite way to use ss! It shows all the running servers.
### -n
use numeric ports (80 not http)
### -P
show PIDs using the socket
### TONS of information
-i -m -o
(-i is in a spiky bubble, -m is in a cloud bubble, and -o is in a heart)
### which sockets ss shows
listening or connections (non-listening/established)?
default: connections
-1: listening
-a: both
which protocols?
default: all
-t: TCP
-u: UDP
-X: unix domain Sockets
### netstat
netstat -tunapl and ss -tunap! do the same thing
netstat is older and more complicated. If you're learning now I'd recommend ss!</div>
|
|
| /comics/nmap/ |
<span class="title">
nmap
</span>
<div class="keywords"></div>
<div class="transcript">### nmap lets you explore a network
which ports are open?
what hosts are up?
security people use it a lot!
### find which hosts are up
`$ nmap-sn 192.168.1.0/24`
`168` is my home network
`-sn` means "ping scan". (not `-s-n` it's `-sn`)
just finds hosts by pinging every one, doesn't port scan
### aggressive scan
`nmap -v -A scanme.nmap.org`
`-A` = aggressive
port, server version, even OS
### -Pn
skip doing a ping scan and assume every host is up. good if hosts block ping (lots do)
### fast port scan
`$ nmap -SS-F 192.168.1.0/24`
just sends a SYN packet to check if each port is open.
I found out which ports my printer has open!
```
80 http
443 https
515 printer
631 ipp
9100 jetdirect
```
### -F
scan less ports: just the most common ones
### -T4 or -T5
scan faster by timing out more quickly
### ♡ check TLS version and ciphers ♡
check if your server still supports old TLS versions
```
$ nmap
--script ssl-enum-ciphers
-p 443 wizardzines.com
```
list all scripts with:
`$ nmap --script-help '*'`</div>
|
|
| /comics/lsof/ |
<span class="title">
lsof
</span>
<div class="keywords"></div>
<div class="transcript">### `lsof`
stands for list open files
stick figure, distraught: somebody has that file open, WHO IS IT?
`lsof`, represented by a rectangle with a goofy face: I can tell you!
### what `lsof` tells you
for each open file:
- `pid`
- file type (regular? directory? FIFO? socket?)
- file descriptor (FD column)
- user
- filename/socket address
### `-p PID`
list the files `PID` has open
### `lof /some /dir`
list just the open files in `some/dir`
### `-i`
list open network sockets (sockets are files!)
examples:
- `-i -n P` (`-n` & `-P` mean "don't resolve host names/ports" [also `-Pni`])"
- `-i : 8080`
- `-i TCP`
- `-i -s TCP:LISTEN`
### find deleted files
`$lsof | grep deleted`
will show you deleted files!
You can recover open deleted files from
`proc/<pid>/fd/<fd>`
(`<pid>` is the process that opened the file)
### `netstat`
another way to list open sockets on Linux is:
`netstat -tunapl`
(tuna, please!)
On Mac, `netstat` has different args.</div>
|
|
| /comics/man-pages/ |
<span class="title">
man page sections
</span>
<div class="keywords"></div>
<div class="transcript">man pages are split up into 8 sections
1 2 3 4 5 6 7 8
`$ man 2 read`
means "get me the man page for `read` from section 2".
There's both
- a program called "read"
- and a system call called "read"
So
`$ man 1 read`
gives you a different man page from
`$ man 2 read`
If you don't specify a section, man will look through all the sections & show the first one it finds.
### man page sections
1. programs
`$ man grep `
`$ man ls`
2. system calls
`$ man sendfile
`$ man ptrace
3. C functions
`$man printf
`$ man fopen
4. devices
`$ man null` for /dev/null docs
5. file formats
`$ man sudoers` for `/etc/sudoers`
`$ man proc` files in `/proc`!
6. games
not super useful. `$man sl` is my favourite from that section
7. miscellaneous
explains concepts!
`$man 7 pipe`
`$ man 7 symlink`
8. sysadmin programs
`$ man apt`
`$ man chroot`</div>
|
|
| /comics/selectors/ |
<span class="title">
CSS selectors
</span>
<div class="keywords"></div>
<div class="transcript">### panel 1
Illustration of a smiling stick figure with curly hair.
person: now that we have the right attitude, let's move on to how CSS actually works!
### div
matches `div` elements
`<div>`
### #welcome
`#` matches elements by `id`
`<div id="welcome">`
### .button
matches elements by `class`
`<a class="button">`
### div .button
match every `.button` element that's a descendent of a `div`
### div.button
match divs with class "`button`"
`<div class="button">`
### div > .button
match every `.button` element that's a direct child of a `div`
### .button, #welcome
matches both `button` and `#welcome` elements
### a[href^="http"]
match `a` elements with a `href` attribute starting with `http`
### a:hover
matches `a` elements that the cursor is hovering over
### :checked
matches if a checkbox or radio button is checked
### tr:nth-child(odd)
match every other child of a parent element</div>
|
|
| /comics/cookies/ |
<span class="title">
cookies
</span>
<div class="keywords"></div>
<div class="transcript">Cookies are a way for a server to store a little bit of information in your browser.
They're set with the `Set-Cookie` response header, like this:
### first request: server sets a cookie
browser, represented by a box with a smiley face: `GET /my-cats`
server, also represented by a box with a smiley face:
```
200 OK
Set-Cookie: user = b0rk; HttpOnly
<response body>
```
(`user` is the name, `b0rk` is the value. `HttpOnly` is the cookie options (expiry goes here))
### Every request after: browser sends the cookie back
browser:
```
GET /my-cats
Cookie: user= b0rk
```
server, thinking: oh, this is b0rk! I don't need to ask them who they are then!
Cookies are used by many websites to keep you logged in. Instead of `user=b0rk` they'll set a cookie like `sessionid=long-incomprehensible-id`. This is important because if they just set a simple cookie like `user=b0rk`, anyone could pretend to be b0rk by setting that cookie!
Designing a secure login system with cookies is quite difficult— to learn more about it, google "OWASP Session Management Cheat Sheet".</div>
|
|
| /comics/testing-checklist/ |
<span class="title">
CSS testing checklist
</span>
<div class="keywords"></div>
<div class="transcript">Finally, it's important to test your site with different browsers, screen sizes, and accessibility evaluation tools.
### browsers
- Chrome
- Safari
- Firefox
- maybe others!
### sizes
- small phone (300px wide)
- tablet (~700px)
- desktop (~1200px)
### accessibility
- colour contrast
- text size
- keyboard navigation
- works with a screen reader
### performance
- fake a slow/high latency network connection!
Illustration of a smiling stick figure with curly hair.
person: the most important thing is to know your users! Check your analytics: if 10% of your users are using IE, test your site on IE!</div>
|
|
| /comics/copy-on-write/ |
<span class="title">
copy on write
</span>
<div class="keywords"></div>
<div class="transcript">### On Linux, you start new processes using the fork() or clone() system call.
calling fork creates a child process that's a copy of the caller
### the cloned process has EXACTLY the same memory.
- same heap
- same stack
- same memory maps
if the parent has 36B of memory, the child will too.
### copying all that memory every time we fork would be slow and a waste of RAM
often processes call `exec` right after `fork`, which means they don't use the parent process's memory basically at all!
### so Linux lets them share physical RAM and only copies the memory when one of them tries to write
process: I'd like to change that memory
Linux: okay! I'll make you your own copy!
### Linux does this by giving both the processes identical page tables.
(same RAM)
but it marks every page as read only.
### when a process tries to write to a shared memory address:
1. there's a page fault=
2. Linux makes a copy of the page & updates the page table
3. the process continues, blissfully ignorant
process, happily: It's just like I have my own copy</div>
|
|
| /comics/oom-killer/ |
<span class="title">
the OOM killer
</span>
<div class="keywords">[linux2]</div>
<div class="transcript"></div>
|
|
| /comics/cpu-scheduling/ |
<span class="title">
CPU scheduling
</span>
<div class="keywords">[linux2]</div>
<div class="transcript"></div>
|
|
| /comics/http2/ |
<span class="title">
HTTP/2
</span>
<div class="keywords"></div>
<div class="transcript">HTTP/2 is a new version of HTTP. Here's what you need to know:
### A lot isn't changing
All the methods, status codes, request/response bodies, and headers mean exactly the same thing in HTTP/2.
before (HTTP/1.1):
```
method: GET
path: /cat.gif
headers:
- Host: examplecat.com
- User-Agent: curl
```
after (HTTP/2):
```
method: GET
path: /cat.gif
authority: examplecat.com
headers:
- User-Agent: curl
```
one change:
Host header => authority
#### HTTP/2 is faster
Even though the data sent is the same, the way HTTP/2 sends it is different. The main differences are:
- It's a binary format (it's harder to ```tcpdump``` traffic and debug)
- Headers are compressed
- Multiple requests can be sent on the same connection at a time
before (HTTP/1.1):
→ request 1
response 1 ←
→ request 2
response 2 ←
after (HTTP/2):
→ request 1
→ request 2
response 2 ←
response 1 ← (out of order is ok)
(one TCP connection)
All these changes together mean that HTTP/2 requests often take less time than the same HTTP/1.1 requests.
### Sometimes you can switch to it easily
A lot of software (CDNs, nginx) let clients connect with HTTP/2 even if your server still only supports HTTP/1.1.
1. Firefox to CDN: HTTP/2 request
2. CDN to your server: HTTP/1.1 request
3. your server to CDN: HTTP/1.1 response
4. CDN to Firefox: HTTP/2 response</div>
|
|
| /comics/tar/ |
<span class="title">
tar
</span>
<div class="keywords"></div>
<div class="transcript">### panel 1
The tar file format combines many files into one file.
a.txt
b.txt
dir/c.txt
tar files aren't compressed by themselves. Usually you gzip them: .tar.gz or .tgz!
### panel 2:
Usually when you use the 'tar' command, you'll run some incantation.
To unpack a tar.gz, use:
```tar -xzf file.tar.gz``
person 1: what's xzf?
person 2: let's learn!
### panel 3: -X is for extract
into the current directory by default (change with -C)
### panel 4: -C is for create
makes a new tar file!
### panel 5: -t is for list
lists the contents of a tar archive
### panel 6: -f is for file
which tar file to create or unpack
### panel 7: tar can compress / decompress
-z gzip format (.gz)
-j bzip2 format (.bz2)
-J x2 format (.xz)
& more! see the man page
### panel 8: putting it together
list contents of a .tar.bz2:
```$tar tvf file.tar.bz2 ```
j = verbose
create a .tar.gz:
```$ tar -c2f file.tar.gz dir/```
dir/ = files to go in the archive</div>
|
|
| /comics/unix-domain-sockets/ |
<span class="title">
unix domain sockets
</span>
<div class="keywords"></div>
<div class="transcript">### unix domain sockets are files
```
$ file mysock.sock
socket
```
the file's permissions determine who can send data to the socket.
### they let 2 programs on the same computer communicate
Docker uses Unix domain sockets, for example!
process: GET/container (HTTP request)
Docker: Here you go!
### There are 2 kind of unix domain sockets
- `stream`: Like TCP! Lets you send a continuous stream of bytes
- `datagram`: Like UDP! Let you send discrete chunks of data
### advantage 1
Lets you use file permission to restrict access to HTTP/database services!
`chmod 600 secret.sock`
This is why Docker uses a unix domain socket. (lock icon)
evil process: run evil container
Linux, nonplussed: permission denied
### advantage 2
UDP sockets aren't always reliable (even on the same compute).
unix domain datagram sockets ARE reliable! And they won't reorder packets!
Process: I can send data and I KNOW it'll arrive
### advantage 3
You can send a file descriptor over a unix domain socket. Useful when handling untrusted input files.
process: here's a file I downloaded from sketchy.com (putting it into video decoder, a sandboxed process)</div>
|
|
| /comics/iptables/ |
<span class="title">
iptables
</span>
<div class="keywords"></div>
<div class="transcript">### panel 1:
iptables lets you create rules to match network packets and accept/drop/modify them
It's used for firewalls and NAT
### tables have chains. chains have rules.
tables:
- `filter`
- `nat`
- `mangle`
- `raw`
- `security`
chains:
- `INPUT`
- `FORWARD`
- `PREROUTING`
- etc
rules: like `-s 10.0.0.0/8 -j DROP`
### `iptables-save`
This prints out all iptables rules. You can restore them with `iptables-restore` but it's also the easiest way to view all rules.
### `-j TARGET`
Every iptables rule has a target (what to do with matching packets). Options:
- `ACCEPT, DROP, RETURN`
- the name of an iptables chain
- an extension (man iptables.extensions)
Popular: `DNAT, LOG, MASQUERADE`
### tables have different chains
filter: `INPUT, OUTPUT, FORWARD`
mangle: `INPUT, OUTPUT, FORWARD, PREROUTING, POSTROUTING`
nat: `OUTPUT, PREROUTING, POSTROUTING`
It helps to know when packets get processed by a given table/chain (eg locally generated packets go through `FILTER` and `OUTPUT`
### you can match lots of packet attributes
- `-s`: src ip
- `-d`: tcp/udp
- `-p`: dst ip
- `-i`: network interface
- `-m`: lots of things! (bpf rules! gcroups! ICMP type! cp! conntrack state! more!
For more, run `$ man iptables-extensions`</div>
|
|
| /comics/tshark/ |
<span class="title">
tshark
</span>
<div class="keywords">[tcpdump]</div>
<div class="transcript">### Wireshark is an amazing graphical packet analysis tool
("Wireshark" has hearts around it)
tshark is the command line version of Wireshark
it can do 100x more things than tcpdump (heart)
### `-Y`
filter which packets are captured
```
tshark -y
'http.request.method
== "GET"
```
(uses Wireshark's SUPER POWERFUL filter language)
### `-d`
is for "decode as"
tells tshark what protocol to interpret a port as
Example: 8888 is often HTTP!
```
$tshark
-d tcp.port==8888,http
```
### `-T FORMAT`
Output format. My favourites:
- json
- fields: csv/tsv
(for these above two you can specify which fields you want with `-e`)
- text: default summary
### `-e`
Which fields to output. Ex:
```
$tshark -T fields
-e http.request.method
-e http.request.uri
-e ip.dst
```
(supports WAY more protocols than HTTP)
```
GET /foo 92.183.216.34
POST /bar 10.23.38.132
```
### `-r file.pcap`
analyze packets from a file instead of the network
### `-w`
(same as tcpdump)
Write captured packets to a file. If `-w file.pcap` has permission issues, try `tshark -w - > file.pcap`</div>
|
|
| /comics/explain/ |
<span class="title">
EXPLAIN
</span>
<div class="keywords"></div>
<div class="transcript">Sometimes queries run slowly, and `EXPLAIN` can tell you why!
2 ways you can use `EXPLAIN` in PostgreSQL: (other databases have different syntax for this)
1. Before running the query (`EXPLAIN SELECT... FROM ...`)
This calculates a query plan but doesn't run the query.
I always run EXPLAIN on a query. before running it on my production database. I won't risk overloading the database with a slow query!
2. After running the query `(EXPLAIN ANALYZE SELECT ... FROM...)`
person 1: why is my query so slow?
person 2: `EXPLAIN ANALYZE` runs the query and analyzes why it was slow
Here are the EXPLAIN ANALYZE results from PostgreSQL for the same query run on two tables of 1,000,000 rows: one table that has an index and one that doesn't
`EXPLAIN ANALYZE SELECT * FROM users WHERE id = 1`
unindexed table:
```
Seq Scan on users
Filter: (id = 1)
Rows Removed by Filter: 999999 Planning time: 0.185 ms
Execution time: 179.412 ms
```
"Seq Scan" means it's looking at each row (slow!)
indexed table:
```
Index Only Scan using users_id_idx on users
Index Cond: (id = 1)
Heap Fetches: 1
Planning time: (3.411 ms
Execution time: 0.088 ms
```
the query runs 50 times faster with an index</div>
|
|
| /comics/cat/ |
<span class="title">
cat
</span>
<div class="keywords"></div>
<div class="transcript">### cat concatenates files
`$ cat myfile.txt` prints contents of myfile.txt|
`$ cat *.txt` prints all .txt files put together!
### you can use cat as an EXTREMELY BASIC text editor:
1. Run $ cat > file.txt
2. type the contents (don't make mistakes (smiley face))
3. press ctrl+d to finish
### cat -n
prints out the file with line numbers!
1. Once upon a midnight..
2. Over many a quaint.
3. While I nodded, nearly
### zcat
cats a gzipped file!
Actually just a 1-line shell script that runs `gzip -cd`, but easier to remember.
### tee
`tee file.txt` will write. its stdin to both stdout and file.txt
`stdin` > `tee a.txt` > `stdout` and `a.txt`
### how to redirect to a file owned by root
`$ sudo echo "hi">> x.txt`
this will open x.txt as your user, not as root, so it fails!
`$ echo "hi" I sudo tee -a x.txt` will open x.txt as root (smiley face)</div>
|
|
| /comics/find/ |
<span class="title">
find
</span>
<div class="keywords"></div>
<div class="transcript">### find searches a directory for files
`find /tmp -type d -print`
`tmp`: directory to search
`-type d`: which files
`-print`: action to do with the files
There are my favourite find arguments!
### -name/-iname
case insensitive
the filename! eg
`-name '*.txt'`
### -path /-ipath
search the full path!
`-path /home/*/*.go`
### -type [TYPE]
f: regular file
d: directory
1: symlink
and more!
### -maxdepth NUM
only descend NUM levels when searching a directory.
### -Size O
find empty files! Useful to find files you created by accident
### -exec COMMAND
action: run COMMAND on every file found
### -print0
print null-separated filenames
Use with xargs -O!
### -delete
action: delete all files found
### locate
The locate command searches a database of every file on your system.
good: faster than find
bad: can get out of date
### $ sudo updatedb
updates the database</div>
|
|
| /comics/take-breaks/ |
<span class="title">
debugging is hard. take breaks.
</span>
<div class="keywords">[debugging]</div>
<div class="transcript"></div>
|
|
| /comics/segfaults/ |
<span class="title">
segmentation faults
</span>
<div class="keywords">[memory linux2]</div>
<div class="transcript"></div>
|
|
| /comics/css-isnt-easy/ |
<span class="title">
CSS isn't easy
</span>
<div class="keywords"></div>
<div class="transcript">### CSS seems simple at first
```
h2 {
font-size: 22px;
}
```
Illustration of a smiling stick figure with curly hair.
person: ok this is easy!
### and it is easy for simple tasks
image of a page with header and text underneath
a layout like this is simple to implement!
### but website layout is not an easy problem
image of a page with a logo, header, text, sidebar, and multiple images
this needs to adjust to so many screen sizes!
### the spec can be surprising
TRY ME!
CSS 2.1: setting `overflow: hidden;` on an inline-block element changes its vertical alignment
Illustration of a stick figure with curly hair, looking worried.
person: weird!
### and all browsers have bugs
Safari: I don't support flexbox for `<summary>` elements
person: ok fine
### accept that writing CSS is gonna take time
person: if I'm patient I can fix all the edge cases in my CSS and make my site look great everywhere!</div>
|
|
| /comics/page-faults/ |
<span class="title">
page faults
</span>
<div class="keywords"></div>
<div class="transcript">### every Linux process has a page table
`*` page table `*`
| virtual memory address | physical memory address |
|--------------------------|--------------------------|
| 0x19723000 | 0x1422000 |
| 0x19724000 | 0x1423000 |
| 0x1524000 | not in memory |
| 0x1844000 | 0x4a000 read only |
### some pages are marked as either:
- read only
- not resident in memory
when you try to access a page that's marked "not resident in memory" it triggers a ! page fault !
### what happens during a page fault?
- the MMU sends an interrupt
- your program stops running
- Linux kernel code to handle the page fault runs
Linux, represented by a box with a smiley face: I'll fix the problem and let your program keep running
### "not resident in memory" usually means the data is on disk!
virtual memory:
Illustration of a bar that is about 60% filled in purple, labelled "in RAM". The remaining 40% is filled in orange and labelled "on disk"
Having some virtual memory that is actually on disk is how `swap` and `nmap` work
### how swap works
1. run out of RAM
Illustration where RAM bar is completely full, disk bar still has lots of room
2. Linux saves some RAM data to disk
Some of the RAM bar has now been moved over to the disk bar
3. mark those pages as "not resident in memory" in the page table
There are arrows between the RAM and disk bars, and the empty portion of the RAM bar is labelled "not resident"
4. When a program tries to access the memory, there's a ! page fault !
5. Linux: time to move some data back to RAM!
Illustration of virtual memory and RAM, with arrows running back and forth between them
6. if this happens a lot, your program gets VERY SLOW
program, sadly: I'm always waiting for data to be moved in & out of RAM</div>
|
|
| /comics/network-protocols/ |
<span class="title">
network protocols
</span>
<div class="keywords">[linux2]</div>
<div class="transcript"></div>
|
|
| /comics/parameter-expansion/ |
<span class="title">
bash parameter expansion
</span>
<div class="keywords"></div>
<div class="transcript">## panel 1: `${...}` is really powerful
person: "it can do a lot of string operations, my favourite is search/replace
## panel 2: `${var}`
same as `$var`
## panel 3: `${&#35;var}`
length of the string or array `var`
example:
```
$ x=panda
$ echo ${#x}
5
```
### panel 4: `${var/bear/panda}`
search & replace. Example:
```
$ x="I'm a bearbear!
$ echo ${x/bear/panda} # replace 1 instance of 'bear'
I'm a pandabear!
$ echo ${x//bear/panda} # replace every instance of 'bear'
I'm a pandapanda!
```
### panel 5: `${var:-othervar}`
use a default value if `var` is unset/null
Example:
```
echo ${asdf:-some default value}
```
### panel 6: `${var:?some error}`
prints "some error" and exits if `var` is null or unset
### panel 7: `${var#pattern}` and `${var%pattern}`
remove the prefix/suffix `pattern` from `var.
Example:
```
$ x=motorcycle.svg
$ echo "${x%.svg}"
motorcycle
```
### panel 8: `${var:offset:length}`
get a substring of `var`. Example:
```
$ x='panda bear time'
$ echo ${x:6:4}
time
```
### panel 9
person: "there are LOTS more, look up 'bash parameter expansion'!"
</div>
|
|
| /comics/coalesce/ |
<span class="title">
COALESCE
</span>
<div class="keywords"></div>
<div class="transcript">`COALESCE` is a function that returns the first argument you give it that isn't `NULL`
```
COALESCE(NULL, 1, 2) => 1
COALESCE(NULL, NULL, NULL) => NULL
COALESCE(4, NULL, 2) => 4
```
#### 2 ways you might want to use `COALESCE` in practice:
1. Set a default value:
In this table, a `NULL` discount means there's no discount, so we use `COALESCE` to set the default to O:
```
SELECT name,
price - COALESCE(discount, 0) as net_price
FROM products
```
products:
| name | price | discount |
|----------|---------|------------|
| orange | 200 | NULL |
| apple | 100 | 23 |
| lemon | 150 | NULL |
query output:
| name | net_price |
|----------|-------------|
| orange | 200 |
| apple | 77 |
| lemon | 150 |
2. Use data from 2 (or more!) different columns
This query gets the best guess at a customer's state:
```
SELECT customer,
COALESCE(mailing_state, billing_state, ip_address_state) AS state
FROM addresses
```
(Mailing address, most accurate. If not, try billing address. As a last resort, use their IP address)
| customer | mailing_state | billing_state | ip_address_state |
|------------|-----------------|-----------------|--------------------|
| 1 | Bihar | Bihar | Bihar |
| 2 | NULL | Kerala | Kerala |
| 3 | NULL | NULL | Punjab |
| 4 | Gujarat | Punjab | Gujarat |
| state |
|------------|
| Bihar |
| Kerala |
| Punjab |
| Gujarat |
</div>
|
|
| /comics/single-quote/ |
<span class="title">
single quote your strings
</span>
<div class="keywords"></div>
<div class="transcript">In some SQL implementations (like PostgreSQL), if you double quote a string it'll interpret it as a column name:
smiling stick figure with short curly hair:
```
SELECT * FROM cats
WHERE name "ms piggy" ;
```
postgres:
```
error: column "ms piggy"
does not exist
```
person, thinking: right, I need to use single quotes
Here's a table explaining what different quotes mean in different SQL databases. "Identifier" means a column name or table name.
Sometimes table names have special characters like spaces in them so it's useful to be able to quote them.
| | single quotes ('miss piggy') | double quotes ("miss piggy") | backticks (`miss piggy`) |
|---------------|--------------------------------|----------------------------------|----------------------------|
| MySQL | string | string or identifier | identifier |
| PostgreSQL | string | identifier | invalid |
| SQLite | string | string or identifier | identifier |
| SQL server | string | string or identifier | invalid |
person: I always use single quotes for strings in SQL queries! It keeps me (and others!) from getting confused.</div>
|
|
| /comics/mmap/ |
<span class="title">
mmap
</span>
<div class="keywords"></div>
<div class="transcript">### what's mmap for?
person 1: I want to work with a VERY LARGE FILE but it won't fit in memory
person 2: You could try mmap!
(mmap = "memory map")
### load files lazily with mmap
When you mmap a file, it gets mapped into your program's memory.
2 TB file: 2 TB of virtual memory
but nothing is ACTUALLY read into RAM until you try to access the memory.
(how it works: page faults!)
### how to mmap in Python
```
import mmap f= open("HUGE.txt")
mm= mmap.mmap (f. filenol), 0)
```
(this won't read the file from disk! Finishes ~instantly.)
`print (mm C-1000:7)`
this will read only the last 1000 bytes!
### sharing big files with mmap
three processes: we all want to read the same file!
mmap: no problem!
Even if 10 processes mmap a file, it will only. be read into memory once
### dynamic linking uses mmap
program: I need to use libc.so.6 (standard library)
ld dynamic linker: you too eh? no problem. I always mmap, so that file is probably loaded into memory already.
### anonymous memory maps
- not from a file (memory set to by default)
- with `MAP.SHARED`, you can use them to share memory with a subprocess!</div>
|
|
| /comics/processes/ |
<span class="title">
processes
</span>
<div class="keywords"></div>
<div class="transcript">## what's in a process?
### PID
process: process #129 reporting for duty!
### USER and GROUP
from offscreen: who are you running as?
process: julia!
### ENVIRONMENT VARIABLES
like `PATH`! you can set them with
`$ env A=val./program`
### SIGNAL HANDLERS
process 1: I ignore `SIGTERM`!
process 2: I shut down safely!
### WORKING DIRECTORY
Relative paths (./blah) are relative to the working directory! `chdir` changes it.
### PARENT PID
PID 129 -> PID 147 -> PID 1 (`init`) is everyone's ancestor
### COMMAND LINE ARGUMENTS
see them in `/proc/PID/cmdline`
### OPEN FILES
very open file has an offset.
process: I've read 8000 bytes of that one
### MEMORY
heap! stack! shared libraries! the program's binary! mmaped files!
### THREADS
sometimes one
sometimes LOTS
### CAPABILITIES
process 1: I have `CAP_PTRACE`
process 2: well I have `CAP_SYS_ADMIN`
### NAMESPACES
process: I'm in the host network namespace
container process: I have my own namespace!</div>
|
|
| /comics/libc/ |
<span class="title">
libc
</span>
<div class="keywords">[linux2]</div>
<div class="transcript"></div>
|
|
| /comics/attitude-matters/ |
<span class="title">
when debugging, your attitude matters
</span>
<div class="keywords">[debugging]</div>
<div class="transcript"></div>
|
|
| /comics/overlay-filesystems/ |
<span class="title">
overlay filesystems
</span>
<div class="keywords"></div>
<div class="transcript">### how layers work: `mount -t overlay`
smiling stick figure with curly hair: can you combine these 37 layers into one filesystem?
linux, represented by Tux the penguin: yes! Just run `mount —t overlay` with the right parameters!
### `mount -t overlay` has 4 parameters
- `lowerdir`: list of read-only directories
- `upperdir`: directory where writes should go
- `workdir`: empty directory for internal use
- `target`: the merged result
### `upperdir`: where all writes go
when you create, change, or delete a file, it's recorded in the upperdir.
usually this starts out empty and is deleted when the container exits
### lowerdir: the layers. read only.
smiling stick figure with curly hair: you can run `$ mount -t overlay` inside a container to gee all the lower dirs that were combined to create its filesystem!
### here's an example!
```
$ mount -t overlay overlay -o
lowerdir=/lower , upperdir=/upper , workdir=/work /merged
$ ls /upper
cat.txt dog.txt
$ ls /lower
dog. txt bird.txt
$ ls /merged
cat.txt dog.txt bird.txt
```
the merged version of dog.txt is the one from the upper directory</div>
|
|
| /comics/shell/ |
<span class="title">
what's a shell?
</span>
<div class="keywords">[linux2]</div>
<div class="transcript"></div>
|
|
| /comics/check-assumptions/ |
<span class="title">
debugging tips: check your assumptions
</span>
<div class="keywords">[debugging]</div>
<div class="transcript"></div>
|
|
| /comics/inodes/ |
<span class="title">
inodes
</span>
<div class="keywords">[linux2]</div>
<div class="transcript"></div>
|
|
| /comics/pipes/ |
<span class="title">
pipes
</span>
<div class="keywords"></div>
<div class="transcript">### panel 1
Sometimes you want to send the output of one process to the input of another
```
$ ls | wc -l
53
```
(53 files!)
### a pipe is a pair of 2 magical file descriptors
Illustration of a tube where the left side is labelled "IN" and the right side is labelled "OUT". There is an arrow between them. "IN" is labelled "pipe input" and "OUT" is labelled "pipe output"
`stdin` -> `ls` -> IN -> OUT -> `wc` -> `stdout`
### panel 3
when `ls` does write (IN, "hi") `wc` can read it!
read (OUT) -> "hi"
Pipes are one way -> You can't write to OUT.
### Linux creates a buffer for each pipe
`ls` -> IN [Buffer: data waiting to be read] OUT -> `wc`
If data gets written to the pipefaste than it's read, the buffer will fill up.
When the buffer is full, writes to IN will block (wait) until the reader reads. This is normal & ok (smiley face).
### what if your target process dies?
-> `ls` -> [dead IN face] [dead OUT face] -> [dead `wc` face] ->
If `wc` dies, the pipe will close and `ls` will be sent `SIGPIPE`. By default, `SIGPIPE` terminates your process.
### named pipes
`$ mkfifo my-pipe`
This lets 2 unrelated pocesses communicate through a pipe
process 1, wearing a hat:
```
f=open(./my_pipe)
f.write("hi!\n")
```
process 2, with curly hair:
```
f=open(./my_pipe)
f.readline() <- "hi!"
```</div>
|
|
| /comics/learn-one-thing/ |
<span class="title">
learn one thing at a time
</span>
<div class="keywords">[debugging]</div>
<div class="transcript"></div>
|
|
| /comics/ping/ |
<span class="title">
ping
</span>
<div class="keywords"></div>
<div class="transcript">### ping checks if you can reach a host and how long the host took to reply
`$ping health.gov.au`
output:
`... time=253ms...`
Australia is 17,000 km from me. at the speed of light it's still far!
### ping works by sending an ICMP packet and waiting for a reply
ping: to: health.gov.au hello!
health.gov.au: I'm here!
### myth: if a host doesn't reply to ping, that means it's down
Some hosts never respond to ICMP packets. This is why traceroute shows "..." sometimes.
ping: hello!
host (thinking): not listening!!
### traceroute tells you the path a packet takes to get to a destination
me → my ISP → NYC → Sacramento → Australia
### example traceroute
`$ traceroute health.gov.au`
`1: 192.168.1.1 3ms` ← router
`2:...yul.ebox.ca 12 ms` ← ISP
`...`
`8: NYC4. ALTER.NET 24 ms` ← here the packet crossed the USA! from NYC- Sacramento!
`9: SAC1.ALTER.NET 97 ms`
`...`
`16: health.gov.au 253ms` ← crossing the US takes time
### mtr
like traceroute, but nicer output! try it!
### last panel
look up how traceroute works (using TTLs!) it's simple + cool!</div>
|
|
| /comics/kill/ |
<span class="title">
kill
</span>
<div class="keywords"></div>
<div class="transcript">
### kill doesn't just kill programs
you can send ANY signal to a program with kill!
`$ kill -SIGNAL PID`
(name or number)
### which signal kill sends
name num
```
kill => SIGTERM 15
kill -9 => SIGKILL 9
kill -KILL => SIGKILL 9
kill -HUP => SIGHUP
kill -STOP => SIGSTOP
```
### kill -l lists all signals.
1. HUP
2. INT
3. QUIT
4. ILL
5. TRAP
6. ABRT
7. BUS
8. FPE
9. KILL
10. USR1
11. SEGV
12. USR2
13. PIPE
14. ALRM
15. TERM
16. STKFLT
17. CHLD
18. CONT
19. STOP
20. TSTP
21. TTIN
22. TTOU
23. URG
24. XCPU
25. XFS2
26. VTALRM
27. PROF
28. WINCH
24. POLL
30. PWR
31. SYS
### killall -SIGNAL NAME
signals all processes called NAME
for example:
`$ killall firefox`
useful flags:
-w: wait for all signaled processes to die
-i: ask before signalling
### pgrep
prints PIDs of matching running programs
pgrep fire matches firefox firebird
NOT bash firefox.sh
To search the whole command line (eg bash firefox.sh), use `pgrep -f`
### pkill
same as pgrep, but signals PIDS found. Example:
`$ pkill -f firefox`
I use pkill more than killall these days.</div>
|
|
| /comics/terminals/ |
<span class="title">
terminals
</span>
<div class="keywords">[linux2]</div>
<div class="transcript"></div>
|
|
| /comics/branch-pointer-commit/ |
<span class="title">
a branch is a pointer to a commit
</span>
<div class="keywords">[git]</div>
<div class="transcript">A branch in git is a pointer to a commit SHA
master → 2e9fab
awesome-feature → 3bafea
fix-typo → 9a9a9a
Here's some proof! In your favourite git repo, run this command:
```$ cat .git/refs/heads/master```
"master" is just a text file with the commit SHA master points at!
Understanding what a branch is will make it WAY EASIER to fix your branches when they're broken: you just need to figure out how to get your branch to point at the right commit again!
3 main ways to change the commit a branch points to:
- ```git commit``` will point the branch at the new commit
- ```git pull``` will point the branch at the same commit as the remote branch
- ```git reset COMM T_SHA``` will point the branch at ```COMM T_SHA```</div>
|
|
| /comics/file-buffering/ |
<span class="title">
file buffering
</span>
<div class="keywords"></div>
<div class="transcript">### panel 1
person with short curly hair, distressed and surrounded by question marks: I printed some text but it didn't appear on the screen. why??
cheerful person with long straight hair: time to learn about flushing!
### On Linux, you write to files & terminals with the system call <3 `write` <3
process, represented by a box with a smiley face: please write "I <3 cats" to file #1 (`stdout`)
Linux, also represented by a box with a smiley face: okay!
### I/O libraries don't always call `write` when you print
`printf("I <3 cats");`
`printf`: I'll wait for a newline before actually writing
This is called buffering and it helps save on syscalls.
### 3 kinds of buffering
(defaults vary by library)
1. None. this is the default for `stderr`
2. Line buffering (write after newline). The default for terminals.
3. "full" buffering (write in big chunks). The default for files and pipes.
### flushing
(little picture of a toilet)
To force your I/O library to write everything it has in its buffer right now, call `flush`~
`stdio`: I'll call `write` right away!
### when it's useful to flush
- when writing an interactive prompt!
Python example:
`print ("password: ", flush=True)`
- when you're writing to a pipe/socket
program: no seriously, actually write to that pipe please</div>
|
|
| /comics/hash-functions/ |
<span class="title">
hash functions
</span>
<div class="keywords"></div>
<div class="transcript"></div>
|
|
| /comics/openssl/ |
<span class="title">
openssl
</span>
<div class="keywords"></div>
<div class="transcript">### openssl is a tool for doing *SSL things*
(aka TLS)
- inspect certificates
- create CSRs
- sign certificates
It uses the OpenSSL library (or LibreSSL)
### inspect a certificate
```
$ openssl x509 -in
FILE.crt -noout -text
```
This works for files ending in .crt or .pem! Try it out:
you probably have certs in `usr/share/ca-certificates`
### look at a website's certificate
```
$openssl s_client
-showcerts -connect
google.com:443
```
happy little stick figure with curly hair: pipe this to openssl x509 to parse!
### panel 4
certificate authority, represented by a box with a neutral expression: please upload a CSR
person: a WHAT?!
to get a SSL cert for your website, you need to make a file called a "certificate signing request."
### make a CSR
```
$ openssl req -new
-sha256 -key FILE.key
-out FILE.csr
```
make a `FILE.key` with `$ openssl genrsa`
### `md5/sha1/sha25b/sha512`
Not quite SSL but useful:
`$openSSL md5 FILE`
computes the md5sum of FILE. Same for other digests
`$ openssl LIST -digestcommands` shows all supported digests.</div>
|
|
| /comics/redirects/ |
<span class="title">
bash redirects
</span>
<div class="keywords"></div>
<div class="transcript">### panel 1: unix programs have 1 input and 2 outputs
When you run a command from a terminal, the input & outputs go
to/from the terminal by default.
Picture of a program (represented by a box with a smiley face) with 1 arrow coming in and 2 arrows out. The arrows are numbered 0, 1, and 2, and there's a
comment: "each input/output has a number, its "file descriptor")
**arrow 0 (coming into program): `<` redirects stdin**
`wc < file.txt` and `cat file.txt | wc` both read `file.txt` to wc's stdin
```
wc < file.txt
cat file.txt
```
**arrow 1 (coming out of program): `>` redirects stdout**
```
cmd > file.txt
```
**arrow 2 (coming out of program): `2>` redirects stderr**
```
cmd 2> file.txt
```
### panel 2: `2>&1` redirects stderr to stdout
```
cmd > file.txt 2>&1
```
Illustration of cmd, represented by a box with a smiley face. There is one arrow, labelled "sdout(1)", leading to a box labelled "file.txt". There is a second arrow coming out of cmd, labelled "stderr(2)". Then, there's a squiggly third arrow, labelled "2>&1", that leads from "stderr(2)" to "file.txt".
### panel 3: `/dev/null`
your operating system ignores all writes to `/dev/null`
```
cmd > /dev/null
```
picture of stdout going to a trash can (`/dev/null`) and stderr still going to the terminal
### panel 2: sudo doesn't addect redirects
your bash shell opens a file to redirect to it, and it's running as you. So
```
$ sudo echo x > /etc/xyz
```
won't work. do this instead:
```
$ sudo echo x | tee /etc/xyz
```
</div>
|
|
| /comics/updating-dns/ |
<span class="title">
why updating DNS is slow
</span>
<div class="keywords">[dns]</div>
<div class="transcript"></div>
|
|
| /comics/shellcheck/ |
<span class="title">
shellcheck
</span>
<div class="keywords"></div>
<div class="transcript">### shellcheck finds problems with your shell scripts
`$ shellcheck my-script.sh`
shellcheck: oops, you can't use in an `if [ ... ]`!
### it checks for hundreds of common shell scripting errors
shellcheck: hey, that's a bash- only feature but your script starts with `#!/bin/sh`
### every shellcheck error has a number (like "SC2013")
and the shellcheck wiki has a page for every error with examples! I've learned a lot from the wiki.
### it even tells you about misused commands
shellcheck: hey, it looks like you're not using `grep` correctly here
person: wow I'm not! thanks!
### your text editor probably has a shellcheck plugin
shellcheck: I can check your shell scripts every time you save!
### basically, you should probably use it
bash has too many weird edge cases for me to remember, I love that shellcheck can help me out!</div>
|
|
Внешние ссылки
Кол-во: 5
Ссылки на сторонние сайты
?
Исходящие внешние ссылки передают часть ссылочного веса на чужие сайты. Ссылки на авторитетные ресурсы безопасны; ссылки на мусорные сайты могут навредить репутации страницы.
Внешних ссылок на странице 5 оптимально.
На странице присутствуют ссылки на субдомены 6.
Показать внешние ссылки
| Url | Анкор |
|---|---|
| jvns.ca |
Julia's blog
|
| social.jvns.ca |
<i class="fab fa-mastodon"></i>
|
| bsky.app |
<i class="fab fa-bluesky"></i>
|
| instagram.com |
<i class="fab fa-instagram"></i>
|
| linkedin.com |
<i class="fab fa-linkedin"></i>
|
Конкуренты Готовность: 0%
Конкуренты в Яндексе
Кол-во: 0
Топ сайтов-конкурентов в Яндексе
?
Сайты, чаще всего появляющиеся в ТОПе Яндекса по запросам из семантического ядра этой страницы.
Мы не нашли у вас конкурентов в Яндексе. Сайт или очень молодой или плохо продвигается.
Конкурентов в ТОП-10 Яндекса не нашлось.
Конкуренты в Google
Кол-во: 0
Топ сайтов-конкурентов в Google
?
Сайты, чаще всего появляющиеся в ТОПе Google по запросам из семантического ядра этой страницы.
Конкуренты в Google тоже не найдены. Займитесь продвижением сайта!
Конкурентов в ТОП-10 Google не нашлось.
ЗоЗПП: права потребителей Готовность: 100%
Нарушения
Не выявлены
Признаков дистанционной продажи товаров (интернет-магазина) не обнаружено — требования ЗоЗПП о раскрытии информации продавца к сайту не применяются. Нарушений нет.
ФЗ-149: рекомендательные технологии Готовность: 100%
Нарушения
Не выявлены
Рекомендательные блоки («с этим покупают», «похожие товары» и т.п.) на сайте не обнаружены — требования ст. 10.7 ФЗ-149 к сайту не применяются. Нарушений нет.
ФЗ-38: реклама Готовность: 100%
Нарушения
Не выявлены
Рекламных тематик с обязательными оговорками (медицина, БАД, кредиты и займы, новостройки) на сайте не обнаружено. Нарушений нет.
ФЗ-436: защита детей Готовность: 100%
Нарушения
Не выявлены
Признаков информационной продукции (новости, видео, книги, игры, курсы) не обнаружено — обязательная возрастная маркировка по ФЗ-436 сайту не требуется. Нарушений нет.
Вердикт
Страница https://wizardzines.com/comics готова к продвижению на 66%. Чтобы еще улучшить страницу и попасть на первые места поисковой выдачи необходимо:
Исправьте ошибки в мета-тегах.
Исправьте ошибки оптимизации.
Исправьте ошибки индексации.
Поделитесь с друзьями: