WITH working_hours_table (working_hours, date_at) AS (
VALUES (136, '2024-01-01'::DATE),
(159, '2024-02-01'::DATE),
(159, '2024-03-01'::DATE),
(168, '2024-04-01'::DATE),
(159, '2024-05-01'::DATE),
(151, '2024-06-01'::DATE),
(184, '2024-07-01'::DATE),
(176, '2024-08-01'::DATE),
(168, '2024-09-01'::DATE),
(184, '2024-10-01'::DATE),
(167, '2024-11-01'::DATE),
(168, '2024-12-01'::DATE)
)
SELECT * FROM working_hours_table;
Поиск
Найдено 13 статьи по слову "sql"
Виртуальная таблица SQL рабочих часов в 2024 году
SQL запрос для таблицы с нулевыми значениями - контроль трекинга в Jira
Сам запрос, здесь берем за последние 8 дней:
select u.display_name as username, u.lower_user_name, day, SUM(wl.timeworked / 3600) as timeworked_hours
from cwd_user u
CROSS JOIN
(select generate_series(
date_trunc('day', now() - interval '7 day'),
date_trunc('day', now()),
'1 day'::interval
) as day
) as days
left join worklog wl on wl.author = concat('JIRAUSER', u.id) AND date_trunc('day', wl.startdate) = day
where u.active = 1
group by username, u.lower_user_name, day
order by username, day;
Пример того, что получается:
Потом это можно собрать в Pivot-таблицу в Superset:
Настройка в Metrics
выглядит так:
CASE
WHEN SUM(timeworked_hours) is null THEN 0
ELSE SUM(timeworked_hours)
END
Какие самые большие таблицы в MySQL?
SELECT CONCAT(table_schema, '.', table_name),
CONCAT(ROUND(table_rows / 1000000, 2), 'M') rows,
CONCAT(ROUND(data_length / ( 1024 * 1024 * 1024 ), 2), 'G') data,
CONCAT(ROUND(index_length / ( 1024 * 1024 * 1024 ), 2), 'G') idx,
CONCAT(ROUND(( data_length + index_length ) / ( 1024 * 1024 * 1024 ), 2), 'G') total_size,
ROUND(index_length / data_length, 2) idxfrac
FROM information_schema.TABLES
ORDER BY data_length + index_length DESC
LIMIT 50;
Источник: https://highload.today/vybor-samykh-bolshikh-tablits-iz-mysql/
Если поломался pip на macOS
Например, ругается на zlib, хотя он установлен:
File "/usr/local/Cellar/python@3.7/3.7.9_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/distutils/command/build_ext.py", line 340, in run
self.build_extensions()
File "/private/var/folders/3r/04yr8dd57896ccmx1f86ptnr0000gn/T/pip-install-lmm5ssql/Pillow/setup.py", line 694, in build_extensions
raise RequiredDependencyException(f)
__main__.RequiredDependencyException: zlib
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/private/var/folders/3r/04yr8dd57896ccmx1f86ptnr0000gn/T/pip-install-lmm5ssql/Pillow/setup.py", line 918, in <module>
raise RequiredDependencyException(msg)
__main__.RequiredDependencyException:
The headers or library files could not be found for zlib,
a required dependency when compiling Pillow from source.
Please see the install instructions at:
https://pillow.readthedocs.io/en/latest/installation.html
То можно сделать следующее:
python3 -m pip install --user --force-reinstall pip
После этого у меня все установилось. Если не поможет - то можно понизить версию python через brew и не забывайте про brew doctor.
Битрикс редиректит на старый домен
После переноса сайта на другой домен или ip-адрес он может начать редиректить, при заходе на него, на старый сайт.
Ситуация может быть в конструкции кода редиректа, например:
<?php
header('Location: http://oldsite.example')
Но, возможно, что это не привязано к коду. И в коде решение найти будет проблематично. Тогда, скорее всего, дело в системе безопасности битрикса. Для того, чтобы ее убрать, необходимо зайти в консоль MySQL и выполнить следующую команду:
> DELETE FROM b_module WHERE `ID`='security';
Query OK, 1 row affected (0.001 sec)
Что такое Docker и что делать, если ваша команда его уже использует?
Что такое вообще этот docker и зачем он нужен?
Он обеспечивает изоляцию выполняемых программ в нем от окружения (программного обеспечения и настроек) вашей операционной системы.
Например, вы работаете над проектом, который использует PHP версии 7. И вдруг к вам на техподдержку приходит проект, который работает максимум на PHP 5.3. Что делать? Если не использовать Docker (или подобное ПО), то вам придется иметь на вашей рабочей машине две версии PHP и разруливать их. Учитывая остальное необходимое для работы приложения ПО, система довольно быстро замусоривается и вполне могут начаться конфликты между ПО, который необходим для одного проекта и неприемлим для другого.
Вы можете рассматривать контейнер docker’а как легковесную виртуальную машину (аналог vmware, virtualbox и т.п.). Только без графического интерфейса и выполняющую определенную программу.
Некоторые термины
Проект - исходный код и конфигурации проекта, над которым вы работаете, обычно находится в одном git-репозитории.
Образ - операционная система и набор программ, которые можно использовать для создания контейнера (программистам проще представлять его как “Класс”). Примеры - Ubuntu 18.04 с установленным PHP 7.1; Debian с установленным nginx; CentOS с установленным MySQL 5.7.
Контейнер - созданный на основе образа экземпляр, может накапливать внутри себя изменения (программистам проще представлять его как “Объект, экземпляр класса”).
Какая разница между командами docker и docker-compose?
Команда docker
просто выполняет команду, которая следует в параметрах, например docker run hello-world
запустит образ hello-world
и покажет результат его выполнения.
Команда docker-compose
работет с конфигурациями (файлы формата *.yml
), которые содержат инструкции для сборки проекта. Также, он может запускать несколько контейнеров сразу, а не только один как команда docker
.
Для разработки обычно используется docker-compose
, т.к. он позволяет удобно передавать конфигурацию сборки между разработчиками.
Я только получил проект, что делать?
Для начала надо поднять проект локально. Для этого выполняется команда:
docker-compose up
Параметр up
создает необходимые для работы проекта контейнеры. Если контейнеры уже были созданы, то он запускает их.
В самом простом случае этого должно быть достаточно чтобы запустить проект и начать работу.
Что за параметр -f
?
Вам могла попадаться команда вида:
docker-compose -f docker-compose-dev.yml up
Параметр -f <путь_к_файлу_yml>
позволяет указать путь к файлу конфигурации для запуска проекта.
Дело в том, что когда мы не указываем этот параметр, то это равнозначно -f docker-compose.yml
- т.е. это стандартный путь к файлу конфигурации.
Т.е., две следующие команды - равнозначны (делают одно и то же):
docker-compose up
docker-compose -f docker-compose.yml up
Но, возможно есть несколько файлов конфигурации (например, один запускает только базу данных - docker-compose-db.yml
, другой целиком бекенд - docker-compose-backend.yml
, третий проект в продакшн режиме - docker-compose-production.yml
), тогда и пригождается эта команда. В ней можно указать полный путь, например, /home/user/myproject/myconfigs/my-docker-compose.yml
. Его можно применять для любого из параметров (up
, down
, start
, stop
, build
и т.п.). Ставится всегда перед параметром, т.е. docker-compose -f <путь> <параметр start|stop|down|up|build>
.
Что за параметр -d
?
Это запуск проекта в фоновом режиме.
Например:
docker-compose up -d
Поднимает проект в фоне, т.е. вы не увидите логов приложения без особых команд. Ставится всегда после параметра, т.е. docker-compose <параметр> -d
.
Я закончил работу с проектом, что делать?
Можно выполнить одну из двух команд.
Эта команда просто остановит контейнеры, то есть вы сможете быстро их запустить позже (командой docker-compose start
):
docker-compose stop
А эта команда остановит и удалит контейнеры проекта, то есть вы освободите место на жестком диске, но запуск контейнеров будет производится дольше:
docker-compose down
Помните, что если вы использовали особую конфигурацию для поднятия проекта (параметр -f
), то его же надо использовать и для этих команд, например, docker-compose -f docker-compose-db.yml stop
.
Как посмотреть, какие контейнеры сейчас запущены?
Эта команда покажет запущенные контейнеры:
docker ps
А эта все созданные контейнеры:
docker ps -a
По названию контейнеров можно понять, какой проект работает. Лучше всего, когда вы запускаете только тот проект, с которым работаете, а остальные выключаете, тогда количество проблем будет минимально.
Как проще всего развернуть Django-проект через Docker
Приведу здесь пошаговое руководство. Как устанавливать и использовать сам фреймворк здесь не описано, так что, при необходимости, обратитесь к официальной документации .
Структура проекта
<span>1.</span> Начнем с приложения. Создадим директорию, в которой будет проект (здесь я создаю его в домашней директории, может находиться где угодно):
$ mkdir ~/my_app
В корне будут храниться файлы конфигураций, так что приложение сгенерирем в поддиректории.
<span>2.</span> Сгенерируем в этой директории Django-приложение:
$ django-admin startproject app
<span>3.</span> Базово настроим Django-проект:
$ cd ~/my_app/
$ virtualenv -p python3.6 venv
$ source venv/bin/activate
$ pip install django
$ pip install python-dotenv
$ pip install psycopg2-binary
$ pip install gunicorn
$ pip freeze > ./app/requirements.txt
Объясню решение по поводу venv
. Рекомендую сделать виртуальное окружение на уровень выше приложения, чтобы он не мешал при сборке докер-образа в будущем (чтобы не отправлялся контекст в докер при сборке и образ собирался быстрее).
Из requirements.txt
удалите строку pkg-resources==0.0.0
(такой версии не существует и она сломает установщик).
В my_app/app/app/settings.py
надо переменные для БД брать из файла .env
(см. документацию к python-dotenv
):
import os
from dotenv import load_dotenv
load_dotenv()
SECRET_KEY = os.getenv("SECRET_KEY")
DEBUG = bool(os.getenv("DEBUG"))
# ...
ALLOWED_HOSTS = ['*']
# ...
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.getenv('POSTGRES_DB'),
'USER': os.getenv('POSTGRES_USER'),
'PASSWORD': os.getenv('POSTGRES_PASSWORD'),
'HOST': os.getenv('POSTGRES_HOST'),
'PORT': os.getenv('POSTGRES_PORT'),
},
}
# ...
STATIC_URL = '/static/'
STATICFILES_DIRS = (
# os.path.join(BASE_DIR, '..', "frontend", "src"),
)
STATIC_ROOT = os.path.join(BASE_DIR, '..', 'public', 'static')
MEDIA_ROOT = os.path.join(BASE_DIR, '..', 'public', 'media')
MEDIA_URL = '/media/'
# ...
<span>4.</span> Создаем файл .env
в корне (~/my_app/.env
), пример содержимого:
SECRET_KEY=1234567890
DEBUG=1
POSTGRES_DB=db
POSTGRES_USER=user
POSTGRES_PASSWORD=password
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
<span>5.</span> Теперь создадим docker-compose конфигурацию, которая поможет нам при разработке. Положим файл в корень проекта:
Файл docker-compose.yml
:
version: '3'
services:
db:
image: postgres:11-alpine
env_file:
- .env
volumes:
- ./postgresql/dumps:/code/dumps
- ./postgresql/data:/var/lib/postgresql/data
restart: always
ports:
- "${POSTGRES_PORT}:5432"
В данном файле можно обратить внимание на env_file - это откуда будут применены переменные окружения (логин, пароль, имя базы данных при первом создании).
Также, если вы не хотите, чтобы при рестарте компьютера контейнер с базой данных автоматически запускался, то удалите строчку restart: always
И последнее - все хранилища будут находиться в директории проекта.
<span>6.</span> Протестируем, что все нормально работает для разработки:
$ cd ~/my_app
$ docker-compose up -d
$ source venv/bin/activate
$ python app/manage.py migrate
<span>7.</span> Инициализируем в корне приложения git-репозиторий и настроем удаленный репозиторий (наконец-то бесплатные приватные репозитории на github), например:
$ cd ~/my_app/
$ git init
$ git remote add origin https://github.com/crusat/test.git
И не забудьте сделать файл .gitignore
, например:
*.pyc
*.log
__pycache__
/app/venv/
db.sqlite3
.DS_Store
/public/*
!/public/favicon.ico
/.idea/
.vscode/
*.history
/reports/
.coverage
*.swp
/htmlcov/
*.ipynb
.env
nohup.out
/postgresql/
tmp
И запушить:
$ git add .
$ git commit -am "initial"
$ git push -u origin master
Подготовка к деплою
<span>8.</span> Регистрируем на докер хабе (можно использовать gitlab registry и т.п.) новый репозиторий https://cloud.docker.com/repository/create - в него мы будем пушить образы. В будущем для этого можно сделать автоматическую сборку, но пока делаем в ручном режиме, для понимания. Назовем репозиторий, например, “test”.
<span>9.</span> Теперь надо сбилдить образ, который мы будем деплоить. Для этого в директории ~/my_app/app/
создадим файл Dockerfile
:
FROM python:3.6-stretch
ENV PYTHONUNBUFFERED 1
# Здесь можно добавлять пакеты, которые необходимы для работы приложения
RUN apt update && apt install -y python3-dev
WORKDIR /code
# Сначала копируем requirements.txt, для того, чтобы образ собирался быстрее (см. слои докера)
COPY requirements.txt /code/
RUN pip install -r requirements.txt
# Далее копируем сам код приложения
COPY . /code/
WORKDIR /code/
EXPOSE 8000
И файл run.sh
там же с содержимым:
#!/usr/bin/env sh
python ./manage.py migrate
python ./manage.py collectstatic --noinput
gunicorn --forwarded-allow-ips=* --bind 0.0.0.0:8080 -w 2 app.wsgi:application
Запускаем билд, потом авторизуемся на удаленном сервере, затем пушим в удаленный репозиторий докерхаба.
$ docker build -t crusat/test .
$ docker login
$ docker push crusat/test
Замените “crusat/test” на ваше имя пользователя и имя репозитория.
<span>10.</span> Теперь подготовим docker-compose.yml
для удаленного сервера.
Создаем директорию ~/my_app/deploy
Создаем файл ~/my_app/deploy/docker-compose.yml
с содержимым:
version: '3'
services:
server:
image: nginx:alpine
restart: always
depends_on:
- web
ports:
- '80:80'
- '443:443'
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./public:/code/public
web:
image: crusat/test:latest
command: sh -c "/code/run.sh"
restart: always
env_file:
- .env
depends_on:
- db
volumes:
- ./public:/code/public
db:
image: postgres:10-alpine
restart: always
env_file:
- .env
volumes:
- ./postgres/data:/var/lib/postgresql/data
- ./postgres/dumps:/dumps
Замените в этом файле “crusat/test” на ваши данные.
Также, создайте в этой директории файл .env
аналогичным тому, который лежит в корне.
И положите файл nginx.conf
там же со следующим содержимым:
# daemon off;
worker_processes auto;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
multi_accept on;
use epoll;
}
http {
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
types_hash_max_size 2048;
client_max_body_size 1G;
include /etc/nginx/mime.types;
server {
listen 80;
server_name _;
# gzip begin
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;
# gzip end
location /media/ {
root /code/public;
expires max;
try_files $uri$args $uri =404;
}
location /static/ {
root /code/public;
expires max;
try_files $uri$args $uri =404;
}
location = /favicon.ico {
alias /code/public/favicon.ico;
}
location / {
proxy_pass http://web:8000;
proxy_set_header Host $http_host;
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;
}
}
}
Удаленная машина
<span>1.</span> Для начала надо зарегистрировать новый сервер. Я использую хостинг https://vscale.io и Ubuntu (в данный момент последняя LTS это 18.04). При создании добавьте свой публичный ключ. Возможно, сервера на 512 мб ОЗУ не будет достаточно и придется использовать сервер на 1 гб ОЗУ.
<span>2.</span> Заходим на сервер, например:
$ ssh root@123.123.123.123
<span>3.</span> Устанавливаем зависимости:
$ apt update && apt install -y curl
<span>4.</span> Устанавливаем Docker и docker-compose:
$ curl -sSL https://get.docker.com/ | sh; curl -L https://github.com/docker/compose/releases/download/1.21.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose
<span>5.</span> Создаем нового пользователя (назовем его deploy
) и добавляем его к группе Docker, чтобы не требовался root-доступ для работы с докером:
$ adduser deploy
$ usermod -aG docker deploy
<span>6.</span> Проверяем, что все работает нормально:
$ su deploy
$ docker run hello-world
Должно появиться следующее (если вывелось это, то все работает нормально):
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:2557e3c07ed1e38f26e389462d03ed943586f744621577a99efb77324b0fe535
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
<span>7.</span> Теперь копируем содержимое директории deploy
(~/my_app/deploy
) в директорию на сервере (/home/deploy/my_app
) и устанавливаем владельца, также поменяйте пароли и секретные ключи в файле окружения .env
.
$ chown -R deploy:deploy /home/deploy/my_app
Пример содержимого .env
:
SECRET_KEY=MubREzkP5GNMxBCHE3wOhuo49zpEjZMUEhoAjkvVujEl3AUD
DEBUG=
POSTGRES_DB=db
POSTGRES_USER=user
POSTGRES_PASSWORD=snm2LfPnas1Fb7d8
POSTGRES_HOST=db
POSTGRES_PORT=5432
<span>8.</span> Теперь необходимо авторизоваться на реджистри, забрать последний образ и развернуть приложение:
$ su deploy
$ docker login
$ cd /home/deploy/my_app
$ docker-compose pull && docker-compose down && docker-compose up -d
<span>9.</span> Заходим по IP-адресу сервера, все должно работать. При необходимости подключаем домен (ставим А-запись домена на регистраторе на IP-адрес сервера).
Починить все базы данных и таблицы MySQL
В терминале (не в консоли mysql) выполните следующую команду:
$ mysqlcheck -u root -p -A --auto-repair
Пример ответа:
...
website.b_adv_banner_2_country OK
website.b_adv_banner_2_day OK
website.b_adv_banner_2_group OK
website.b_adv_banner_2_page OK
website.b_adv_banner_2_site OK
website.b_adv_banner_2_stat_adv OK
website.b_adv_banner_2_weekday OK
...
Для поиска: repair database, repair table.
Создание бекапов в Яндекс.Диск (Ubuntu)
Описание
Скрипт умеет:
- Делать бекапы директорий, например, /etc.
- Делать бекапы поддиректорий (разделяя их), например, /var/www/*.
- Делать дампы MySQL.
- Делать дампы PostgreSQL.
- Загружать все это дело в Яндекс.Диск.
Подготовка
Для начала необходимо получить токен для Яндекс.Диска.
Для этого:
1. Перейдите по этому URL https://oauth.yandex.ru/client/new.
2. Название введите любое, например, “server_backup” без кавычек.
3. Права выберите пункт “Яндекс.Диск REST API” и в нем “Доступ к папке приложения на Диске”.
4. Снизу нажмите “Подставить URL для разработки”.
5. Сохраните.
Вам выдаст подобные результаты:
ID: 61bf56f1e72a4112b83e1db9e44dbe9c
Пароль: 74087cd13d2247c48661c75617916b75
Callback URL: https://oauth.yandex.ru/verification_code
- Переходим по URL https://oauth.yandex.ru/authorize?response_type=token&display=popup&client_id=%ID%
Обратите внимание. Замените в URL выше %ID% на то, что получили выше, т.е. в моем примере - “61bf56f1e72a4112b83e1db9e44dbe9c”. - Нажимаем кнопку “Разрешить”.
- Копируем полученный токен и вставляем его в скрипт в YD_TOKEN (см. ниже).
Настройка
Скачайте файл backup_yd.sh и сохраните его на сервере.
Далее, вам необходимо изменить переменные в блоке “Init variables”:
# Базовый путь для сохранения бекапов.
BASE_BACKUP_DIR="/home/user/backups"
# Токен Yandex.Disk.
YD_TOKEN=""
# Пароль от пользователя root СУБД MySQL. Если она не используется, оставьте пустым.
MYSQL_ROOT_PASSWORD=""
# Делать дампы СУБД PostgreSQL?
# Пустая строка - нет
# "1" - да
USE_POSTGRESQL=""
# Список директорий, которые необходимо бекапить.
# В данном примере будет забекаплена директория /etc как архив etc.tar.gz и
# все поддиректории /var/www с соответствующими именами.
declare -a DIRS_FOR_BACKUP=('/etc' '/var/www/*');
# Размеры чанков (т.к. максимальный размер файлов ограничен, то необходимо
# разрезать архив на несколько частей. Чанк - и есть эта часть).
SPLIT_BY="200MiB"
Также, необходимо дать права на запуск:
chmod +x ./backup_yd.sh
Проверяем
Для проверки запустим скрипт:
./backup_yd.sh
В директории %BASE_BACKUP_DIR% будет создана директория с текущей датой, в ней поддиректории для файлов и дампов баз данных.
Все файлы бекапов разрезаются на чанки.
Затем будет произведена загрузка на Яндекс.Диск и директория будет удалена.
Примечание: Чтобы собрать бекап из чанков, используйте команду cat:
cat mybackup.tgz_* > mybackup.tgz
Настраиваем ежедневные бекапы по времени
Запускаем cron:
crontab -e
Добавляем следующую строку (впишите правильный путь до файла backup_yd.sh)
0 3 * * * /bin/bash /home/user/backups/backup_yd.sh
После этого сохраняйте и выходите из редактирования cron.
Все, теперь каждый день в 3 часа ночи будет создаваться новый бекап и загружаться в ваш Яндекс.Диск.