Как вы нашли спутницу(-ка) жизни?
Линуксоиды, которые таки нашли себе жену (мужа), как вам это удалось?
Многоженцам (многомужницам) предлагается ориентироваться на первый брак, а разводившимся — на последний.
>>> Результаты
Линуксоиды, которые таки нашли себе жену (мужа), как вам это удалось?
Многоженцам (многомужницам) предлагается ориентироваться на первый брак, а разводившимся — на последний.
>>> Результаты
Кто какие фильтры\конфиги\плагины использует? Может кто-то юзает какие-то плагины, которые 60fps делают или что-то оригинальное
В общем старая клавиатура приказала долго жить, а на новой нет SysReq) Как-то не обратил на это внимание) Больше заботило как видны кириллические символы. Тут все отлично и даже ё есть)
Но как теперь вылезти из зависания?) Советы вроде PrintScrn не помогут. На PrintScrn нет функционала SysReq и даже там нет подписи SysReq. И потому и нет)
Можно как-то что-то переназначить?)
Многие пользователи Linux с большим стажем даже не подозревают о существовании этих замечательных инструментов, которые способны облегчить им жизнь…
( читать дальше... )
Я нашёл геймпад от Xbox 360 для PlayStation 5. Я в сайте-конструктуре сделал дизайн DualSense в стиле Xbox 360 Controller.
DualSense полноценно поддерживает Linux и для этого не нужны утилиты по типу DS4Windows.
Если через 5 лет появится эмулятор PS5 - то DualSense на Linux хорошая тема.
Перемещено hobbit из screenshots
Перемещено hobbit из talks
Не секрет, что практически все функции в Golang возвращают ошибки. И тут два пути: или игнорировать или обрабатывать в iferr. Игнорировать почти никогда не получается, так что выбор невелик и код превращается в
val, err := SomeFunc()
if err != nil {
..do some..
}
буклетов по алгоритмам и структурам данных ща море разливанное
поэтому охота найти вот такой у которого в частности
Алгоритмы поиска в глубину и в ширину обобщаются в алгоритм поиска использующего очередь с приоритетами где глубина это обратнохронологическое(что вырождает приоритетную очередь в стек) а ширина это прямохронологическое(что вырождает в обычную очередь) - а иная функция приоритета это А*
ну и с наблюдением что та. же приоритетная очередь ( как дерево а не пирамида) - это эдакий отложеная(yield и прочий async :) ) мердж-сортировка где в каждом внутреннем узле начато слияние (выяснен первый элемент двух списков) и остановлено
т.е ищется учебник по алгосам и структурам данных где как можно большее количество структур данных и алгосов на них показаны как специализации более универсальных конструкций
Данный топик про игры в юниксовом терминале. Здесь я буду на регулярной основе (в идеале) описывать в отдельном комментарии какую-нибудь игру. В стартер-посте будут ссылки на эти комментарии. Обзор будет не очень подготовленным, поэтому не ждите литературных изысков. Но тем не менее те, кто любит подобное красноглазие, смогут познакомиться с играми и выбрать на свой вкус понравившуюся вещицу. Данная тема создана по аналогии с соседним топиком про стимовские игры.
Приглашаются красноглазые задротики, которые любят тупить в консольку между сессиями компиляния очередного ядра линукса. Можете подписываться на темку, ставить лайк, прожимать колокольчик или что тут у вас принято.
Теги для поисковых ботов (жрите мои любимые ботики): ascii games, terminal games, ncurses games, tty games, console games, cli games, tui games, text-based games, command line games, игры в терминале, игры в консоле, игры для командной строки.
!!!NEW!!! 1. 8f - Терминальный вариант карточной игры Сумасшедшие восьмёрки (Crazy Eights).
Фичи:
by-ts
, а его ник - классом ts-nick
odd
, а четные - классом even
Включает коды из других проектов:
Скриншоты
https://images.linuxforum.ru/images/2024/03/23/IZOBRAZENIE1471e033edbdb898.png https://images.linuxforum.ru/images/2024/03/23/IZOBRAZENIE.png
Установка
Ctrl+A
и вставьте код скрипта, затем нажмите Ctrl+S
.Более простой способ установки
Установка на телефон
Настройка
В настройках сайта «Форматирование по умолчанию» должно быть LORCODE
.
Чтобы выключить опцию, поставьте false
в строчке с соответствующей опцией. Чтобы включить опцию, поставьте true
.
NEW_TO_OLD_SEARCH_BY_DEFAULT HIDE_NEWS_AND_GALLERY ADD_TAGS_AND_DOCS TECH_ONLY_BY_DEFAULT HIDE_TAG_CLOUD HIDE_STARS HIDE_REACTIONS
Создание юзерстилей
/*Чередующиеся сообщения разных цветов*/
.messages .odd {
background-color: #FBFCFB;
}
.messages .even {
background-color: #F0FFF7;
}
/*Кастомизируем вид кнопок редактора сообщений*/
#btn-i {
font-style: italic;
}
#btn-quote::before {
content: 'Цитата';
}
#btn-quote span {
display: none;
}
// ==UserScript==
// @name LORScriptPack
// @description Пак скриптов для ЛОРа
// @namespace linux.org.ru
// @include http://www.linux.org.ru/*
// @include https://www.linux.org.ru/*
// @author damix9
// @license MIT
// @version 2.1
// ==/UserScript==
/*
MIT License
Copyright (c) 2024 damix9
Copyright (c) 2022 OpenA
Copyright (c) 2007-2009 Steven Levithan <stevenlevithan.com>
Copyright (с) 2013 Oleksandr Natalenko aka post-factum
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Настройки
const NEW_TO_OLD_SEARCH_BY_DEFAULT = false;
const HIDE_NEWS_AND_GALLERY = false;
const ADD_TAGS_AND_DOCS = true;
const TECH_ONLY_BY_DEFAULT = false;
const HIDE_TAG_CLOUD = false;
const HIDE_STARS = false;
const HIDE_REACTIONS = false;
// Глобальные константы и переменные
const parser = new DOMParser();
const formats = ['jpeg', 'jpg', 'png', 'webp', 'tif', 'tiff'];
let CommentForm = null;
let tagListWrapper = null;
let divPopup = null; let timer = null;
// Функции
function _setup(el, attrs, events) {
if (!el)
return '';
switch (typeof el) {
case 'string':
el = document.createElement(el);
case 'object':
for (const key in attrs) {
attrs[key] === undefined ? el.removeAttribute(key) :
key === 'html' ? el.innerHTML = attrs[key] :
key === 'text' ? el.textContent = attrs[key] :
key in el && (el[key] = attrs[key] ) == attrs[key]
&& el[key] == attrs[key] || el.setAttribute(key, attrs[key]);
}
for (const name in events) {
if (!events[name])
continue;
if (Array.isArray(events[name]))
events[name].forEach(handler => el.addEventListener(name, handler, false));
else
el.addEventListener(name, events[name], false);
}
}
return el;
}
// Возвращает расширение файла, находящегося по адресу url
function _getUrlExt(url) {
let oURL = new URL(url);
let path = oURL.pathname;
return path.split('.').pop().toLowerCase();
}
// Возвращает название темы, выбранной в настройках
function getCurrentTheme() {
let firstLinkNode = document.head.querySelector('link');
let cssUrl = new URL(firstLinkNode.href);
return cssUrl.pathname.split('/')[1]
}
// Добавляет CSS к странице
function addCss(sheet) {
var head = document.head;
let style = _setup('style', { text: sheet });
head.appendChild(style);
}
function strContains(str, phrase) {
return str.indexOf(phrase) !== -1;
}
// В течение 3 секунд показывает всплывающее уведомление с текстом text
function popup(text) {
clearTimeout(timer);
divPopup.innerHTML = text;
divPopup.style.visibility = 'visible';
divPopup.classList.add('shown');
timer = setTimeout(() => {
divPopup.classList.remove('shown');
timer = setTimeout(() => {
divPopup.style.visibility = 'hidden';
}, 1000)
}, 3000)
}
//******************************************************************************************
//
// A CGI program uses the following syntax to add cookie information to the HTTP header:
//
// Set-Cookie: name=value
// [;EXPIRES=dateValue]
// [;DOMAIN=domainName]
// [;PATH=pathName]
// [;SECURE]
//
// This function sets a client-side cookie as above. Only first 2 parameters are required
// Rest of the parameters are optional. If no szExpires value is set, cookie is a session cookie.
//
// Prototype : setCookie(szName, szValue [,szExpires] [,szPath] [,szDomain] [,bSecure])
//******************************************************************************************
function setCookie(szName, szValue, szExpires, szPath, szDomain, bSecure)
{
var szCookieText = escape(szName) + '=' + escape(szValue);
szCookieText += (szExpires ? '; EXPIRES=' + szExpires.toGMTString() : '');
szCookieText += (szPath ? '; PATH=' + szPath : '');
szCookieText += (szDomain ? '; DOMAIN=' + szDomain : '');
szCookieText += (bSecure ? '; SECURE' : '');
document.cookie = szCookieText;
}
//******************************************************************************************
// This functions reads & returns the cookie value of the specified cookie (by cookie name)
//
// Prototype : getCookie(szName)
//******************************************************************************************
function getCookie(szName)
{
var szValue = null;
if(document.cookie) //only if exists
{
var arr = document.cookie.split((escape(szName) + '='));
if(2 <= arr.length)
{
var arr2 = arr[1].split(';');
szValue = unescape(arr2[0]);
}
}
return szValue;
}
//******************************************************************************************
// To delete a cookie, pass name of the cookie to be deleted
//
// Prototype : deleteCookie(szName)
//******************************************************************************************
function deleteCookie(szName)
{
var tmp = getCookie(szName);
if(tmp)
{ setCookie(szName,tmp,(new Date(1))); }
}
// Добавляет к форме отправке сообщения кнопки для редактирования разметки, делает поле ввода сообщения широким
function handleCommentForm(form) {
const TEXT_AREA = form.elements.msg, TITLE_AREA = form.elements.title || { value: '' };
const MARKUP_PANEL = _setup('div', { id: 'markup-panel', class: 'lorcode'});
for (let attrs of [
{ lorcode: 'b' , title: 'Жирный' },
{ lorcode: 'i' , title: 'Курсив' },
{ lorcode: 'u' , title: 'Подчеркнутый' },
{ lorcode: 's' , title: 'Зачеркнутый' },
{ lorcode: 'em' , title: 'Курсив выделения' },
{ lorcode: 'strong' , title: 'Жирный выделения' },
{ lorcode: 'url' , title: 'Ссылка' },
{ lorcode: 'list' , title: 'Список' },
{ lorcode: 'list' , title: 'Нумерованный список', attr: '1' },
{ lorcode: '*' , title: 'Элемент списка' },
{ lorcode: 'pre' , title: 'Преформатированный текст' },
{ lorcode: 'br' , title: 'С новой строки' },
{ lorcode: 'code' , title: 'Код' },
{ lorcode: 'code' , title: 'Bash', attr: 'bash' },
{ lorcode: 'code' , title: 'HTML', attr: 'html' },
{ lorcode: 'code' , title: 'CSS', attr: 'css' },
{ lorcode: 'code' , title: 'JavaScript', attr: 'js' },
{ lorcode: 'code' , title: 'PHP', attr: 'php' },
{ lorcode: 'code' , title: 'SQL', attr: 'sql' },
{ lorcode: 'code' , title: 'Си', attr: 'c' },
{ lorcode: 'code' , title: 'C++', attr: 'cpp' },
{ lorcode: 'code' , title: 'Java', attr: 'java' },
{ lorcode: 'inline', title: 'Код в той же строке' },
{ lorcode: 'user' , title: 'Ник пользователя' },
{ lorcode: 'quote' , title: 'Цитата' }
]) {
attrs.type = 'button';
attrs.id = 'btn-' + attrs.lorcode.toLowerCase();
attrs.class = 'btn btn-default';
let label = _setup('span', { text: attrs.lorcode });
if (attrs.attr) {
let a = attrs.attr.toLowerCase();
attrs.id += `-${a}`;
label.innerHTML += `=${a}`
}
let button = _setup('button', attrs);
button.appendChild(label);
MARKUP_PANEL.append(button)
}
lorcodeMarkup = lorcodeMarkup.bind(TEXT_AREA);
for (let i = 0; i < MARKUP_PANEL.childNodes.length; i++) {
let btn = MARKUP_PANEL.childNodes[i];
btn.addEventListener('click', function(e) {
e.preventDefault();
const tag = this.getAttribute('lorcode');
const attr = this.getAttribute('attr');
lorcodeMarkup(tag, attr)
});
}
TEXT_AREA.parentNode.firstElementChild.after(MARKUP_PANEL);
TEXT_AREA.style = "width: 70em; height: 10em;"
}
// Пишет в поле ввода сообщения текст str, туда, где стоял курсор,
// Ставит курсор в конец добавленного текста и выделяет поле ввода
function injectText(str) {
const txtArea = CommentForm.elements.msg;
let val = txtArea.value,
len = txtArea.value.length,
start = txtArea.selectionStart,
end = txtArea.selectionEnd;
txtArea.value = val.substring(0, start) + str + val.substring(end);
txtArea.selectionStart = txtArea.selectionEnd = start + str.length;
txtArea.focus()
}
// Берет выделенный текст в указанный тег с указанным аттрибутом
// Если тег br или * то ставит их еще и в начале каждой строки выделенного текста
// Всегда вызывать bind() или call(), передав в них textarea, в которой надо делать разметку
function lorcodeMarkup(tag, attr) {
const val = this.value,
end = this.selectionEnd,
start = this.selectionStart,
collp = start === end;
let mtext = '', open = '', close = '',
soff = 0, eoff = 0;
mtext = val.substring(start, end);
switch (tag) {
case 'br':
if (!collp)
mtext = mtext.replace(/\n/gm, '\n'+'[br]');
else
open = '[br]';
break;
case '*':
open = '[*]';
if (!collp)
mtext = mtext.replace(/\[\/?\*\]/g, '').replace(/\n/gm, '\n'+'[*]');
break;
case 'url':
let uri = prompt('Введите адрес ссылки');
if (uri) {
open = `[url=${uri}]`;
close = '[/url]';
}
else {
return;
}
break;
default:
open = attr ? `[${tag}=${attr}]` : `[${tag}]`;
close = `[/${tag}]`;
}
soff = open.length; eoff = open.length + mtext.length;
this.value = val.substring(0, start) + open + mtext + close + val.substring(end);
this.focus();
this.setSelectionRange(start + soff, start + eoff);
this.dispatchEvent(new InputEvent('input', { bubbles: true }))
}
// Отправлет сообщение с текстом msg в тему c id topic
function sendMessageToTopic(topic, msg) {
let newTab = open(`https://www.linux.org.ru/add_comment.jsp?topic=${topic}&msg=${msg}`, '_blank');
newTab.focus()
}
// Обратиться к пользователю по нику
function castUser(nick) {
injectText('[user]' + nick + '[/user], ')
}
// Цитировать. Аргументы опциональны. Если указаны, то цитировать с ником.
function quote(nick, link) {
const wSelect = window.getSelection();
if (wSelect.isCollapsed) {
return
}
let simple = (nick === undefined) && (link === undefined);
let text = simple ? '' : '\n[user]' + nick + '[/user] [url=' + link + ']пишет[/url]:\n';
text += '[quote]' + wSelect.toString().trim() + '[/quote]' + '\n';
injectText(text)
}
// Отправить модераторам ссылку на сообщение с нарушением правил
function reportHam(link) {
let violation = prompt('Введите текст жалобы');
if (violation == null) {
return
}
let specTopicId = getCookie('SPECTOPIC_ID');
let text = link;
if (violation != "") {
text += '%0D%0A%5Bbr%5D' + violation; // перенос строки и [br]
}
if (!(specTopicId)) {
alert('Не задан спецтопик!\nОткройте его (Форум -> Linux-org-ru -> Ссылки на некорректные сообщения) и нажмите кнопку \"Это спецтопик\".');
return
}
sendMessageToTopic(specTopicId, text)
}
// Сохраняет ID текущей темы в cookie SPECTOPIC_ID
function itsSpecTopic() {
let path = window.location.pathname;
let topicId = path.split('/')[3];
let expires = new Date();
expires.setDate(expires.getDate() + 60);
setCookie('SPECTOPIC_ID', topicId, expires, '/');
alert('Спецтопик установлен')
}
let firstLetter = '';
// Обновляет отображаемый список тегов, показывает теги, соответстующие
// поисковому запросу, т.е. начинающиеся на строку, содержащуюся в поле ввода
async function searchTags(e) {
let query = e.target.value.trim().toLowerCase();
let queryFirstLetter = query.charAt(0);
if (queryFirstLetter != firstLetter) {
firstLetter = queryFirstLetter;
if (firstLetter != '') {
let response = await fetch('https://www.linux.org.ru/tags/' + firstLetter);
let txt = await response.text();
let oDoc = parser.parseFromString(txt, 'text/html');
let content = oDoc.getElementById('bd');
let tagList = content.getElementsByTagName('ul')[0];
let oldTagList = tagListWrapper.firstChild;
if (oldTagList) {
tagListWrapper.replaceChild(tagList, oldTagList)
}
else {
tagListWrapper.appendChild(tagList);
}
}
}
let tagList = tagListWrapper.firstChild;
if (tagList) {
for (let i = 0, c = tagList.children.length; i < c; i++) {
let tag = tagList.children[i];
let s = tag.children[0].text;
if (s.startsWith(query)) {
tag.style.display = 'list-item'
}
else {
tag.style.display = 'none'
}
}
}
}
// Добавляет к сообщению (теме или комментарию) недостающие ссылки внизу.
// Передать DOM Node элемента div.reply сообщения и логин его отправителя.
function addReplyLinks(replyNode, author) {
let links = replyNode.firstElementChild;
let linkToComment = links.lastElementChild.firstElementChild.href;
let nick = _setup(
'a',
{ text: 'Ник', href: linkToComment + '#nick' },
{ click: (e) => { e.preventDefault(); castUser(author) } }
);
let report = _setup(
'a',
{ text: 'Пожаловаться', href: linkToComment + '#report' },
{ click: (e) => { e.preventDefault(); reportHam(linkToComment) } }
);
let simpleQuote = _setup(
'a',
{ text: 'Цитировать', href: linkToComment + '#quote' },
{ click: (e) => { e.preventDefault(); quote() } }
);
let advancedQuote = _setup(
'a',
{ text: 'Цитировать с ником', href: linkToComment + '#quote' },
{ click: (e) => { e.preventDefault(); quote(author, linkToComment) } }
);
let nickLi = _setup('li'); nickLi.appendChild(nick);
let reportLi = _setup('li'); reportLi.appendChild(report);
let quoteLi = _setup('li'); quoteLi.appendChild(simpleQuote);
let advancedQuoteLi = _setup('li'); advancedQuoteLi.appendChild(advancedQuote);
links.firstElementChild.before(nickLi);
nickLi.after(' ');
links.appendChild(reportLi);
reportLi.before(' ');
links.appendChild(quoteLi);
quoteLi.before(' ');
links.appendChild(advancedQuoteLi);
advancedQuoteLi.before(' ')
}
// Принимает событие клика, копирует в буфер обмена текст поля, на котором кликнули
function copyNick (e) {
e.target.select();
if (document.execCommand('copy')) {
popup('Текст скопирован в буфер обмена')
}
}
// Принимает блок с кодом, выделяет его текст
function selectCode (codeNode) {
let range = document.createRange();
range.selectNodeContents(codeNode.firstElementChild);
let selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range)
}
// Принимает блок с кодом, сворачивает/разворачивает его
function toggleCodeSpoiler(codeNode) {
codeNode.classList.toggle('unspoiled')
}
/*
* Date Format 1.2.3
* (c) 2007-2009 Steven Levithan <stevenlevithan.com>
* MIT license
*
* Includes enhancements by Scott Trenda <scott.trenda.net>
* and Kris Kowal <cixar.com/~kris.kowal/>
*
* Accepts a date, a mask, or a date and a mask.
* Returns a formatted version of the given date.
* The date defaults to the current date/time.
* The mask defaults to dateFormat.masks.default.
*/
var dateFormat = function () {
var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
timezoneClip = /[^-+\dA-Z]/g,
pad = function (val, len) {
val = String(val);
len = len || 2;
while (val.length < len) val = "0" + val;
return val;
};
// Regexes and supporting functions are cached through closure
return function (date, mask, utc) {
var dF = dateFormat;
// You can't provide utc if you skip other args (use the "UTC:" mask prefix)
if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
mask = date;
date = undefined;
}
// Passing date through Date applies Date.parse, if necessary
date = date ? new Date(date) : new Date;
if (isNaN(date)) throw SyntaxError("invalid date");
mask = String(dF.masks[mask] || mask || dF.masks["default"]);
// Allow setting the utc argument via the mask
if (mask.slice(0, 4) == "UTC:") {
mask = mask.slice(4);
utc = true;
}
var _ = utc ? "getUTC" : "get",
d = date[_ + "Date"](),
D = date[_ + "Day"](),
m = date[_ + "Month"](),
y = date[_ + "FullYear"](),
H = date[_ + "Hours"](),
M = date[_ + "Minutes"](),
s = date[_ + "Seconds"](),
L = date[_ + "Milliseconds"](),
o = utc ? 0 : date.getTimezoneOffset(),
flags = {
d: d,
dd: pad(d),
ddd: dF.i18n.dayNames[D],
dddd: dF.i18n.dayNames[D + 7],
m: m + 1,
mm: pad(m + 1),
mmm: dF.i18n.monthNames[m],
mmmm: dF.i18n.monthNames[m + 12],
yy: String(y).slice(2),
yyyy: y,
h: H % 12 || 12,
hh: pad(H % 12 || 12),
H: H,
HH: pad(H),
M: M,
MM: pad(M),
s: s,
ss: pad(s),
l: pad(L, 3),
L: pad(L > 99 ? Math.round(L / 10) : L),
t: H < 12 ? "a" : "p",
tt: H < 12 ? "am" : "pm",
T: H < 12 ? "A" : "P",
TT: H < 12 ? "AM" : "PM",
Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
};
return mask.replace(token, function ($0) {
return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
});
};
}();
// Some common format strings
dateFormat.masks = {
"default": "ddd mmm dd yyyy HH:MM:ss",
shortDate: "m/d/yy",
mediumDate: "mmm d, yyyy",
longDate: "mmmm d, yyyy",
fullDate: "dddd, mmmm d, yyyy",
shortTime: "h:MM TT",
mediumTime: "h:MM:ss TT",
longTime: "h:MM:ss TT Z",
isoDate: "yyyy-mm-dd",
isoTime: "HH:MM:ss",
isoDateTime: "yyyy-mm-dd'T'HH:MM:ss",
isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
};
// Internationalization strings
dateFormat.i18n = {
dayNames: [
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
],
monthNames: [
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
]
};
// Принимает событие отправки формы поиска в Google.
// Перенаправляет пользователя на страницу поиска Google по сайту
function searchByGoogle(event) {
event.preventDefault();
let term = document.getElementById('qg').value;
let redirect = 'https://www.google.com/search?q=' + term + ' site:linux.org.ru';
window.location.href = redirect
}
// Основной код
let LOR_CSS = `
.code {
overflow: scroll;
}
.code.spoiled {
overflow-y: scroll;
}
.code pre {
overflow-x: unset;
overflow-y: unset;
word-wrap: initial;
}
pre code {
white-space: pre;
}
.code .spoiler-open {
display: none;
}
#markup-panel .btn {
margin: 2px;
}
#qg {
margin-right: 5px;
}
a img.lorpic {
max-width: 700px;
}
@media (max-width: 900px) {
a img.lorpic {
max-width: 60vw;
height: auto;
}
.popup-message {
width: 90vw;
}
}
.user-tag {
display: none;
}
.popup-message {
visibility: hidden;
opacity: 0;
position: fixed;
right: 20px;
bottom: 20px;
padding: 10px;
width: 300px;
border-style: solid;
transition-property: opacity;
transition-duration: 1s;
transition-timing-function: linear;
}
.shown {
visibility: visible;
opacity: 1;
}
`;
const LOR_DARK = `
.messages .by-ts {
background-color: #3d2300;
}
a img.lorpic {
background-color: #FFC;
}
.popup-message {
border-width: thin;
border-color: #8ae234;
background-color: #033;
}
`;
const LOR_LIGHT = `
.messages .by-ts {
background-color: #FFC;
}
.popup-message {
border-width: medium;
border-color: #000;
background-color: #FC6;
}
div.code {
background-color: #FFF;
}
`;
const LOR_BLACK = `
.ts-nick::after {
content: '[ТС]';
color: #F30;
font-weight: bold;
}
a img.lorpic {
background-color: #FFC;
}
.popup-message {
border-width: thin;
border-color: #8ae234;
background-color: #033;
}
`;
if (HIDE_TAG_CLOUD) {
LOR_CSS += `
.tag-cloud {
display: none;
}
`
}
if (HIDE_STARS) {
LOR_CSS += `
.stars {
display: none;
}
`
}
if (HIDE_REACTIONS) {
LOR_CSS += `
.reactions {
display: none;
}
`
}
const theme = getCurrentTheme();
addCss(LOR_CSS);
if (theme == 'tango') {
addCss(LOR_DARK)
}
else if (theme == 'waltz') {
addCss(LOR_LIGHT)
}
else if (theme == 'black') {
addCss(LOR_BLACK)
}
CommentForm = document.forms.commentForm || document.forms.messageForm;
if (CommentForm) {
handleCommentForm(CommentForm);
}
let firstSign = document.querySelector('footer div.sign');
let TS = firstSign ? firstSign.firstElementChild.textContent : null;
if (TS) {
let nextBlock = firstSign.parentElement.nextElementSibling;
if (nextBlock.className == "reply") {
addReplyLinks(nextBlock, TS)
}
}
let comments = document.getElementById('comments') && document.getElementById('comments').getElementsByClassName('msg-container');
if (comments) {
for (let i = 0, c = comments.length; i < c; i++) {
let sign = comments[i].getElementsByClassName('sign')[0];
let reply = comments[i].getElementsByClassName('reply')[0];
let author = sign.firstElementChild.textContent;
let parentNode = comments[i].parentElement;
if (author == TS) {
parentNode.classList.add('by-ts');
sign.classList.add('ts-nick')
}
// Если индекс комментария в массиве comments четный,
if ((i % 2) == 0) {
// то по счету комментарий нечетный
parentNode.classList.add('odd')
}
else {
parentNode.classList.add('even')
}
// Первый комментарий имеет индекс 0
if (reply) {
addReplyLinks(reply, author)
}
}
}
// Делаем местное время
let times = document.getElementsByTagName("time");
let c = times.length;
for (i = 0; i < c; i++) {
let attrTime = new Date(times[i].getAttribute("datetime", 0));
let nowTime = new Date();
let diff = Math.round(nowTime.getTime() / 1000) - Math.round(attrTime.getTime() / 1000);
let attrDay = new Date(attrTime.getTime());
let nowDay = new Date(nowTime.getTime());
attrDay.setHours(0, 0, 0, 0);
nowDay.setHours(0, 0, 0, 0);
let today = attrDay.getTime() == nowDay.getTime();
let yesterday = (attrDay.getTime() + 86400000) == nowDay.getTime();
let timeText;
if ((strContains(document.URL, "/tracker") || strContains(document.URL, "/notifications"))) {
let minutes = Math.ceil(diff / 60);
if (minutes < 60) {
timeText = minutes + " мин."
}
else if (today) {
timeText = dateFormat(attrTime.getTime(), "HH:MM:ss")
}
else if (yesterday) {
timeText = "вчера " + dateFormat(attrTime.getTime(), "HH:MM:ss")
}
else {
timeText = dateFormat(attrTime.getTime(), "dd.mm.yy HH:MM")
}
}
else {
if (today) {
timeText = "сегодня " + dateFormat(attrTime.getTime(), "HH:MM")
}
else if (yesterday) {
timeText = "вчера " + dateFormat(attrTime.getTime(), "HH:MM")
}
else {
timeText = dateFormat(attrTime.getTime(), "dd.mm.yyyy HH:MM")
}
}
times[i].innerHTML = timeText
}
// Настраиваем меню
if (theme == 'tango' || theme == 'waltz') {
let menu = document.getElementsByClassName('menu')[0].getElementsByTagName('ul')[0]; // Главное меню
if (TECH_ONLY_BY_DEFAULT) {
menu.children[4].firstElementChild.href = '/tracker/?filter=tech';
}
if (HIDE_NEWS_AND_GALLERY) {
// Убираем первые два раздела - новости и галерею
menu.firstElementChild.remove();
menu.firstElementChild.remove();
}
if (ADD_TAGS_AND_DOCS) {
let itmTags = _setup('li'); let itmWiki = _setup('li');
let linkTags = _setup(
'a',
{ href: '/tags/', text: 'Теги' }
);
let linkWiki = _setup(
'a',
{ href: 'http://lorwiki.zhbert.ru/', text: 'Документация', target: '_blank' }
);
itmTags.appendChild(linkTags); itmWiki.appendChild(linkWiki);
menu.appendChild(itmTags);
menu.appendChild(itmWiki);
itmWiki.before(' ');
}
}
// =================================================================================
let related = document.getElementById('related-topics');
if (related) {
let btnItsSpectopic = _setup(
'input',
{ type: 'button', value: 'Это спецтопик' },
{ click: itsSpecTopic }
);
related.before(btnItsSpectopic);
}
// Добавляем всплывающее уведомление
divPopup = _setup(
'div',
{ class: 'popup-message' }
);
document.body.appendChild(divPopup);
// Сворачиваемый и копируемый код
let codes = document.querySelectorAll('div.code');
for (let i = 0, c = codes.length; i < c; i++) {
let code = codes[i];
let linkToggleCodeSpoiler = _setup(
'a',
{ href: '#toggleCodeSpoiler', text: 'Развернуть/Свернуть' },
{ click: (e) => { e.preventDefault(); toggleCodeSpoiler(code) } }
);
let linkSelectCode = _setup(
'a',
{ href: '#selectCode', text: 'Выделить' },
{ click: (e) => { e.preventDefault(); selectCode(code) } }
);
let codeControls = _setup(
'div',
{ class: 'code-controls' }
);
codeControls.appendChild(linkToggleCodeSpoiler);
codeControls.appendChild(linkSelectCode);
linkToggleCodeSpoiler.before('[');
linkSelectCode.before('] [');
linkSelectCode.after(']');
code.before(codeControls)
}
// Картинки
let links = document.getElementsByTagName('a');
for (i = 0, c = links.length; i < c; i++) {
let link = links[i];
if (!link.getAttribute('itemprop')) {
let url = link.href;
let ext = _getUrlExt(url);
if (formats.includes(ext)) {
let content = link.textContent;
if (content != 'Просмотр') {
let image = _setup(
'img',
{ class: 'lorpic', src: url, title: content, alt: url },
);
link.innerHTML = '';
link.target = '_blank';
link.appendChild(image)
}
}
}
}
// ================================================================================
if (window.location.pathname == '/tags/') {
tagSearchBar = _setup('div', { style: 'margin: 20px 0' });
let tagSearchInput = _setup(
'input',
{ placeholder: 'Поиск меток ...', size: 30, autofocus: true },
{ keyup: searchTags }
);
tagSearchBar.appendChild(tagSearchInput);
let tagsFirstLetters = document.getElementsByClassName('tags-first-letters')[0];
tagsFirstLetters.after(tagSearchBar);
tagListWrapper = _setup('span');
tagSearchBar.after(tagListWrapper);
document.getElementsByTagName('section')[0].className = 'tag-cloud'
}
if (window.location.pathname.startsWith('/people')) {
let profile = document.getElementsByClassName('vcard')[0]
if (profile) {
let nick = profile.getElementsByClassName('nickname')[0];
let nickName = '[user]' + nick.textContent.trim() + '[/user]';
profile.appendChild(_setup('br'));
profile.appendChild(_setup('b', { text: 'Копировать ник: ' }));
let copyInput = _setup(
'input',
{ value: nickName, size: nickName.length, readOnly: true },
{ click: copyNick }
);
profile.appendChild(copyInput);
profile.appendChild(_setup('br'))
}
}
if ((window.location.pathname == '/search.jsp') && (window.location.search == '')) {
let searchContainer = document.getElementById('bd');
let hdrGoogle = _setup(
'h1',
{ text: 'Поиск в Google' }
);
let inpGoogle = _setup(
'input',
{ id: 'qg', size: 50, class: 'input-lg', type: 'search', maxlength: 250 }
);
let btnGoogle = _setup(
'button',
{ class: 'btn btn-primary', text: 'Поиск' }
)
let googleSearchBar = _setup(
'form',
{ class: 'control-group' },
{ submit: searchByGoogle }
);
googleSearchBar.appendChild(hdrGoogle);
googleSearchBar.appendChild(inpGoogle);
googleSearchBar.appendChild(btnGoogle);
searchContainer.appendChild(googleSearchBar);
let defaultSortOrder = _setup(
'input',
{ type: 'hidden', name: 'sort', value: 'DATE' }
);
if (NEW_TO_OLD_SEARCH_BY_DEFAULT) {
searchContainer.getElementsByTagName('form')[0].appendChild(defaultSortOrder)
}
}
В awesome расстояние между тегами меньше и выглядит это аккуратней. Может какой-то патч есть, которы позволяет менять размер отступов между тегами?(делать их меньше по ширине(width))
Сделал себе домашний маршрутизатор. Веб на клиентах доступен, но не весь — часть сайтов (и этот среди них) не работают. На самом маршрутизаторе всё открывается.
Схема:
[cli] 192.168.0.2/29
|
----- 192.168.0.0/29
|
br0: 192.168.0.1/29
[rtr]
ppp0: 10.100.9.5/32
|
----- pppoe
|
[isp] 10.100.0.1/32
|
...
Клиент:
root@cli:~# curl -v -k https://www.linux.org.ru -o /dev/null
* Adding handle: conn: 0x7fab74004000
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7fab74004000) send_pipe: 1, recv_pipe: 0
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* About to connect() to www.linux.org.ru port 443 (#0)
* Trying 178.248.233.6...
* Connected to www.linux.org.ru (178.248.233.6) port 443 (#0)
0 0 0 0 0 0 0 0 --:--:-- 0:04:59 --:--:-- 0* Operation timed out after 300448 milliseconds with 0 out of 0 bytes received
0 0 0 0 0 0 0 0 --:--:-- 0:05:00 --:--:-- 0
* Closing connection 0
curl: (28) Operation timed out after 300448 milliseconds with 0 out of 0 bytes received
Роутер:
root@rtr:~# nft list ruleset
table inet home {
chain input {
type filter hook input priority filter; policy drop;
ct state established,related accept
iifname vmap { "lo" : accept, "br0" : jump input_int }
}
chain input_int {
icmp type echo-request accept
ip saddr 192.168.0.2 tcp dport 22 accept
}
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
iifname "br0" accept
}
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
oifname "ppp0" masquerade
}
}
В первом приближении пакеты проходят:
root@rtr:~# tcpdump -i br0
21:07:28.759275 IP 192.168.0.2.62653 > dns.google.domain: 11903+ A? www.linux.org.ru. (34)
21:07:28.759867 IP 192.168.0.2.55189 > dns.google.domain: 56192+ AAAA? www.linux.org.ru. (34)
21:07:28.779138 IP dns.google.domain > 192.168.0.2.62653: 11903 1/0/0 A 178.248.233.6 (50)
21:07:28.781905 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [S], seq 4008111092, win 65535, options [mss 1460,nop,wscale 4,nop,nop,TS val 1102006709 ecr 0,sackOK,eol], length 0
21:07:28.785758 IP 178.248.233.6.https > 192.168.0.2.51398: Flags [S.], seq 3128115892, ack 4008111093, win 5792, options [mss 1460,nop,wscale 9,sackOK,TS val 289594195 ecr 1102006709], length 0
21:07:28.787025 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [.], ack 1, win 8235, options [nop,nop,TS val 1102006714 ecr 289594195], length 0
21:07:28.790257 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [P.], seq 1:179, ack 1, win 8235, options [nop,nop,TS val 1102006717 ecr 289594195], length 178
21:07:28.793882 IP 178.248.233.6.https > 192.168.0.2.51398: Flags [.], ack 179, win 60, options [nop,nop,TS val 289594259 ecr 1102006717], length 0
21:07:28.798772 IP 178.248.233.6.https > 192.168.0.2.51398: Flags [P.], seq 2897:4038, ack 179, win 60, options [nop,nop,TS val 289594264 ecr 1102006717], length 1141
21:07:28.800222 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [.], ack 1, win 8235, options [nop,nop,TS val 1102006726 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:07:32.290387 IP 192.168.0.2.51315 > 178.248.233.6.https: Flags [.], ack 817493168, win 8235, length 0
21:07:33.798702 IP 178.248.233.6.https > 192.168.0.2.51398: Flags [F.], seq 4038, ack 179, win 60, options [nop,nop,TS val 289599264 ecr 1102006726], length 0
21:07:33.995497 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [.], ack 1, win 8235, options [nop,nop,TS val 1102011916 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:07:51.112302 IP 192.168.0.2.51317 > 178.248.233.6.https: Flags [.], ack 1788523727, win 8235, length 0
21:07:57.637922 IP 192.168.0.2.51377 > 178.248.233.6.https: Flags [.], ack 3270250373, win 8235, length 0
21:08:10.959408 IP 192.168.0.2.51378 > 178.248.233.6.https: Flags [.], ack 1734482898, win 8235, length 0
21:08:34.005182 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:08:47.300446 IP 192.168.0.2.51315 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:08:57.645557 IP 192.168.0.2.51377 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:09:06.122845 IP 192.168.0.2.51317 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:09:10.966172 IP 192.168.0.2.51378 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:09:34.514986 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:09:58.156700 IP 192.168.0.2.51377 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:10:02.311781 IP 192.168.0.2.51315 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:10:10.974358 IP 192.168.0.2.51378 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:10:21.132956 IP 192.168.0.2.51317 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:10:34.521112 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:11:34.526793 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:12:29.224679 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102307109 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:29.525558 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102307410 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:29.829200 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102307713 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:30.233351 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102308117 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:30.741193 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102308622 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:31.447212 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102309329 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:32.662818 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102310541 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:34.580798 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:12:34.782531 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102312662 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:36.906159 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102314783 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:39.029305 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102316904 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:41.652656 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102319524 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:43.775462 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102321645 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:45.998680 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102323864 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:48.121683 IP 192.168.0.2.51398 > 178.248.233.6.https: Flags [R.], seq 180, ack 1, win 8235, length 0
root@rtr:~# tcpdump -i ppp0
21:07:28.759660 IP 10.100.9.5.62653 > dns.google.domain: 11903+ A? www.linux.org.ru. (34)
21:07:28.760106 IP 10.100.9.5.55189 > dns.google.domain: 56192+ AAAA? www.linux.org.ru. (34)
21:07:28.778960 IP dns.google.domain > 10.100.9.5.62653: 11903 1/0/0 A 178.248.233.6 (50)
21:07:28.782236 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [S], seq 4008111092, win 65535, options [mss 1460,nop,wscale 4,nop,nop,TS val 1102006709 ecr 0,sackOK,eol], length 0
21:07:28.785532 IP 178.248.233.6.https > 10.100.9.5.51398: Flags [S.], seq 3128115892, ack 4008111093, win 5792, options [mss 1460,nop,wscale 9,sackOK,TS val 289594195 ecr 1102006709], length 0
21:07:28.787245 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [.], ack 1, win 8235, options [nop,nop,TS val 1102006714 ecr 289594195], length 0
21:07:28.790477 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [P.], seq 1:179, ack 1, win 8235, options [nop,nop,TS val 1102006717 ecr 289594195], length 178
21:07:28.793666 IP 178.248.233.6.https > 10.100.9.5.51398: Flags [.], ack 179, win 60, options [nop,nop,TS val 289594259 ecr 1102006717], length 0
21:07:28.798524 IP 178.248.233.6.https > 10.100.9.5.51398: Flags [P.], seq 2897:4038, ack 179, win 60, options [nop,nop,TS val 289594264 ecr 1102006717], length 1141
21:07:28.800404 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [.], ack 1, win 8235, options [nop,nop,TS val 1102006726 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:07:32.290679 IP 10.100.9.5.51315 > 178.248.233.6.https: Flags [.], ack 817493168, win 8235, length 0
21:07:33.798448 IP 178.248.233.6.https > 10.100.9.5.51398: Flags [F.], seq 4038, ack 179, win 60, options [nop,nop,TS val 289599264 ecr 1102006726], length 0
21:07:33.995834 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [.], ack 1, win 8235, options [nop,nop,TS val 1102011916 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:07:51.112551 IP 10.100.9.5.51317 > 178.248.233.6.https: Flags [.], ack 1788523727, win 8235, length 0
21:07:57.638168 IP 10.100.9.5.51377 > 178.248.233.6.https: Flags [.], ack 3270250373, win 8235, length 0
21:08:10.959740 IP 10.100.9.5.51378 > 178.248.233.6.https: Flags [.], ack 1734482898, win 8235, length 0
21:08:34.005553 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:08:47.300740 IP 10.100.9.5.51315 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:08:57.645805 IP 10.100.9.5.51377 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:09:06.123174 IP 10.100.9.5.51317 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:09:10.966463 IP 10.100.9.5.51378 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:09:34.515235 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:09:58.156944 IP 10.100.9.5.51377 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:10:02.312030 IP 10.100.9.5.51315 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:10:10.974612 IP 10.100.9.5.51378 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:10:21.133238 IP 10.100.9.5.51317 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:10:34.521362 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:11:34.527046 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:12:29.224932 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102307109 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:29.525815 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102307410 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:29.829507 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102307713 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:30.233681 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102308117 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:30.741447 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102308622 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:31.447466 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102309329 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:32.663073 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102310541 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:34.581053 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [.], ack 1, win 8235, length 0
21:12:34.782782 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102312662 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:36.906420 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102314783 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:39.029563 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102316904 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:41.652914 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102319524 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:43.775747 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102321645 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:45.998938 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [F.], seq 179, ack 1, win 8235, options [nop,nop,TS val 1102323864 ecr 289594259,nop,nop,sack 1 {2897:4038}], length 0
21:12:48.121943 IP 10.100.9.5.51398 > 178.248.233.6.https: Flags [R.], seq 180, ack 1, win 8235, length 0
Коллеги, плиз поделитесь опытом ( и если есть годные туториалы ну или треды обсуждений) по использования zswap и zram на дешманских VPS c памятью макс 1-2 гига рама .
На них будет запускаться в докерах ( docker-compose) zabbix + postgresql c timescaledb и netflow коллекторы типа akvorado
PS1="\[\033[0;37m\]\342\224\214\342\224\200\$([[ \$? != 0 ]] && echo \"[\[\033[0;31m\]\342\234\227\[\033[0;37m\]]\342\224\200\")[$(if [[ ${EUID} == 0 ]]; then echo '\[\033[0;31m\]\h'; else echo '\[\033[0;33m\]\u\[\033[0;37m\]@\[\033[0;96m\]\h'; fi)\[\033[0;37m\]]\342\224\200[\[\033[0;32m\]\w\[\033[0;37m\]]\n\[\033[0;37m\]\342\224\224\342\224\200\342\224\200\342\225\274 \[\033[0m\]"
Как добавить в этот PS1 вот это?
$(__git_ps1 '(%s)')
Что-то я растерялся из-за обилия [
┌─[user@debian-home]─[~/media/source_project/dj/work/some/auth]
└──╼
Надо сделать
┌─[user@debian-home]─[git_branch_name]-[~/media/source_project/dj/work/some/auth]
└──╼
А то неудобно, иногда сабмодули перескакивают на HEAD-some с мастера, нужно видеть в каком бренче нахожусь
Привет, ЛОР. Подскажи, где бы посмотреть на сложные пипелайны, дабы мудрости перенять и глупость свою уменьшить? В гугле смотрел, но там что-то не очень сложные примеры на первой странице, в мануале гитлаба, я так подозреваю, тоже вводные примеры. Где же найти сложностей? Ну тип что-то вроде ансибл-галактики мож чего есть?
Заметил, что очень многие сидят на надёжных, старых конфигурациях своих редакторов, vim и emacs.
В Neovim решили пойти по пути унификации и внедрили, кажется, с 4й версии tree-sitter.
В Emacs с тормозами, но впилили с 29 версии.
Результат впиливания в Emacs: все major modes идут на юга отдыхать (не нужны). Даже с csharp-mode, который приняли в ядро в 29 версии смешно получилось. Tree-sitter выполняет все задачи, описанные в этом примере.
С чем столкнулся я. Примеров в сети на данный момент практически нет, документация недооформлена, приходится обращаться к остаткам доки замороженных проектов, перенесённых в основную ветку разработки (привет Eglot и команды (или названия) для установки lsp сервера).
В сообществе Neovim с этим более чем полный порядок. Правда тут меня напрягает legacy и ублюдочный синтаксис конфига из-за vim. может после 0.11 версии станет легче, не знаю. И нам, осьминогам, Emacs ближе за возможность поменять всё на свете, даже Cthulhu!..
У кого есть истории успеха? Хорошие, годные статьи и (или) примеры конфигов с новыми фишками 29 версии? Их что-то маловато или я не там ищу.
Потратил кучу времени чтобы найти что-то способное держать 5800X в бусте при полной нагрузке без троттлинга, но при этом не стоящее сотен нефти и способное уместиться в NR200P. И наконец нашел.
280 мм AIO водянки сразу отмел как дорогие (протекающее через неделю говно за 5 тысяч в расчет не берём) и имеющие сомнительную эффективность. Scythe Fuma 2 отсутствует в продаже не только в РФ, но и у белых людей, а Noctua U12A тут стоит неоправданно дорого.
В поисках доступной альтернативы я перекопал кучу тем на reddit, overclock.net и других ресурсах и по итогу остановился на Thermalright Peerless Assassin 120 SE. Топовая башня за свою цену, на ютубе много подробных разборов.
В продаже в РФ этого кулера не оказалось, пришлось идти на али и я чуть было его не заказал, но вовремя наткнулся на Phantom Spirit 120 SE от того же производителя.
По габаритам он такой же как и PA120 SE, но имеет 7 теплотрубок вместо 6 (трубки отлично пропаяны по всей длине и пронизывают всю подошву), чуть более широкую подошву и немного другое расположение лепестков радиатора.
Обошёлся он мне в 3700 рублей вместе с доставкой. Стоковые вентиляторы я сразу выбросил, поскольку Thermalright нормальные делать не умеет, и установил вместо них ADATA XPG VENTO PRO 120 - реинкарнация знаменитого Gentle Typhoon. Вертушки эти шумные на максимальных оборотах, так что пришлось в UEFI кривую настраивать чтобы они раскручивались на полную только при 80+ градусах. За две отдал около 3 тысяч. Ещё 450 рублей за 40x40 мм пластинку PTM7950 вместо стоковой термопасты.
Курва -20 all core, лимиты PBO оставил на motherboard. Гонял Cinebench, Prime95 и y-cruncher - температура была в районе 75°C и камень держал буст по всем ядрам без троттлинга, что для 5800X просто отличный результат. В остальных задачах максимум 70 градусов было.
В итоге примерно за 7 тысяч я получил кулер по эффективности на уровне AIO водянки Arctic Liquid Freezer II 280 или Noctua U12A которые сейчас у нас стоят в 2 раза дороже.
Если вам нужен нормальный воздушный кулер для процессоров под AM4/AM5 или LGA151x/LGA1700 - берите этот.
Всем привет. Пишу небольшую научную статью, для нее разработал простенькую программу, которая делает обработку на нескольких машинах, потом сливает все вместе. Сейчас мне потребовалось в ходе теста устроить локальную проблему: нужно отключить сеть и посмотреть на поведение программы (отключать нужно часто). В контейнер ее не положить, виртуалка тоже не вариант. Отключить адаптер тоже - я это проверяю и уже исследовал. Нужно именно устроить черную дыру для всех пакетов определенного интерфейса. Я пока склоняюсь к варианту iptables и, возможно, route … reject. Но может есть что-то попроще? Например, sysctl может что-то универсальное имеет или же может вообще без вмешательства в систему? Был бы очень признателен за идею.
Как у товарища настроен emacs вот тут https://www.youtube.com/watch?v=p4HH8w3f-8s
Привет!
Стремлюсь улучшить свои навыки в математическом анализе и ищу советов по дополнительным ресурсам для изучения. Прочитал уже книгу Кудрявцева, но хочу найти ещё материалы, такие как рекомендуемые книги или YouTube-каналы, чтобы более глубоко понять эту дисциплину. Буду благодарен за любые рекомендации и советы!
Очень неудобно, когда открываешь броузер и все табы, кроме текущего, являются suspend, перехожу на любой из них и они начинают рефрешиться. Как запретить firefox’у это делать?
следующие → |