• Как отслеживать время нахождения клиента в очереди до момента ответа на вызов оператором?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Для этого не нужно AMI. У команды Queue есть параметры macro и gosub, в которых указывается, соответственно, макрос и подпрограмма, вызываемые в момент соединения оператора с абонентом. Просто сохраняем время помещения клиента в очередь, а при соединении вычисляем время нахождения в очереди.
    ...
    same => n,Set(__start=${EPOCH})
    same => n,Queue(callcenter,CcRt,,,,,,queue-connected)
    ...
    [queue-connected]
    exten => s,1,Set(inQueueTime=$[${EPOCH}-${start}])
    ...

    Затем можно вызвать скрипт через System или напрямую записать данные в базу через ODBC.
    Ответ написан
    Комментировать
  • Обращение к записи БД требует некоторой обработки. Что лучше: обработать в скрипте, который обратился, или в хранимой процедуре в БД?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Прежде чем всё это усложнять описанным вами способом, необходимо определиться с ожидаемыми количествами. Насколько много всего будет переменных, насколько много может быть этих объектов, какие ожидаются частоты этих ваших обращений.
    Ещё нужно определиться как вы планируете редактировать наборы изменяемых переменных. Запишете прямо в БД руками, или нужно делать API для редактирования списков?
    Вы собираетесь скрипт запускать при каждом поступлении новой порции данных? Может правильнее запустить его на ожидание порций из пайпа? Или АПИ сделать поверх http.

    По существу вопроса. Минус хранимых процедур в том, что это код, который хранится вместе с данными. Нужно делать отдельные специфические "приседания", чтобы правильно деплоить и обновлять такой код, хранить его в системе контроля версий, мигрировать от версии к версии...
    Быстродействие в обоих случаях будет зависеть от конкретных действий, которые вы будете каждый раз повторять при "обращениях". Однако при наличии "бутылочного горлышка" в этом месте при реализации через хранимые процедуры вы уже мало что там можете сделать. А вот в коде на питоне можно при необходимости добавить воркеров и таски на длительные операции передавать им через очередь.

    В целом задача звучит так, будто делать её надо максимально простым способом без предварительной оптимизации, которая, скорее всего, и не пригодится. Оптимизировать нужно по факту, когда понятно станет где будут проблемные места.
    Ответ написан
    Комментировать
  • Насколько мой код читабелен?

    gbg
    @gbg Куратор тега C++
    Любые ответы на любые вопросы
    Это все конечно очень хорошо, но в репе лежат симлинки вместо файлов. Так что пока оценка -10/10 - достигнут предельный радиус кривизны рук.
    Ответ написан
    3 комментария
  • Мой exe файл некорректно передаётся, что делать?

    Vindicar
    @Vindicar
    RTFM!
    что значит "текстовый файл передаётся нормально"? Ты первые 2048 байт при приёме выбрасываешь же.
    Ответ написан
    2 комментария
  • Как в логе Mikrotik отображать DNS name а не ip?

    firedragon
    @firedragon
    Не джун-мидл-сеньор, а трус-балбес-бывалый.
    да никак, эта проблема решается постпарсерами. Вы отдаете им логи, а они неторопливо разрешают ip в fqdn
    Ответ написан
    4 комментария
  • Какие есть WEB self-hosted решения для обмена файлами?

    gbg
    @gbg Куратор тега Системное администрирование
    Любые ответы на любые вопросы
    nextcloud, но последнее требование у вас забавное
    Ответ написан
    6 комментариев
  • Dial Patterns для FreePBX?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    от 4760000 до 4809999
    _893047[6-9]XXXX
    _8930480XXXX

    6500000 до 8999999
    _89306[5-9]XXXXX
    _8930[78]XXXXXX

    Вот скрипт, который у меня периодически генерирует новый список экстеншинов региональных операторов для Asterisk в ael-формате.
    https://github.com/Rsa97/Other/blob/main/asterisk/...
    Ответ написан
  • Как сделать очередь из данных между PHP и Python?

    @deliro
    RabbitMQ
    Redis
    NATS Streaming
    Linux FIFO
    Да даже простой HTTP

    Тысячи их
    Ответ написан
    Комментировать
  • Как сделать мониторинг кс го сервера discord.py?

    @cython
    Для мониторинга нужно делать запрос к самому игровому серверу, используя valve a2s протокол. На python есть несколько библиотек, реализующих этот протокол: python-valve, python-a2s
    Пример python-value:
    import valve.source.a2s
    
    SERVER_ADDRESS = (..., ...)
    
    with valve.source.a2s.ServerQuerier(SERVER_ADDRESS) as server:
        info = server.info()
        players = server.players()
    
    print("{player_count}/{max_players} {server_name}".format(**info))
    for player in sorted(players["players"], key=lambda p: p["score"], reverse=True):
        print("{score} {name}".format(**player))

    Пример python-a2s:
    >>> import a2s
    >>> address = ("stomping.kinofnemu.net", 27015)
    >>> a2s.info(address)
    SourceInfo(protocol=17, server_name=" 24/7 Dustbowl :: Nemu's Stomping Ground", map_name='cp_dustbowl',
    folder='tf', game='Team Fortress', app_id=440, player_count=31, max_players=33, bot_count=21,
    server_type='d', platform='l', password_protected=False, vac_enabled=True, version='5579073',
    edf=177, port=27015, steam_id=85568392920040090, stv_port=None, stv_name=None,
    keywords='brutus,celt,couch,cp,dustbowl,increased_maxplayers,nemu,nocrits,nodmgspread,pony,replays,vanilla',
    game_id=440, ping=0.253798684978392)
    
    >>> a2s.players(address)
    [Player(index=0, name='Brutus', score=34, duration=836.4749145507812),
     Player(index=0, name='RageQuit', score=6, duration=1080.8099365234375),
     Player(index=0, name="Screamin' Eagles", score=1, duration=439.8598327636719)]
    
    >>> a2s.rules(address)
    {'coop': '0', 'deathmatch': '1', 'decalfrequency': '10', 'metamod_version': '1.10.7-devV',
     'mp_allowNPCs': '1', 'mp_autocrosshair': '1', 'mp_autoteambalance': '0', 'mp_disable_respawn_times': '0',
     'mp_fadetoblack': '0'}
    Ответ написан
    Комментировать
  • Какие best practices при настройке компьютерного класса под рабочими группами?

    Jump
    @Jump Куратор тега Системное администрирование
    Системный администратор со стажем.
    Вы забыли одну существенную деталь.
    Есть множество программ которые не требуют установки, либо устанавливаются прямо в профиль пользователя.

    Поэтому следует настроить политики ограниченного использования программ - Software Restriction Policy.
    Вот пример настройки.
    В итоге пользователь у вас сможет запустить только указанные в политиках программы.
    Другие исполняемые файлы даже если он скачает - запустить не сможет вообще.

    По поводу запрета на файлы - запись должна быть разрешена только в свою папку и в свой профиль.
    Остальные места - запретить.
    Рабочий стол - да пусть пишут, это удобно для многих, просто удаляйте все лишнее скриптом при логине пользователя. В итоге каждый раз чистый стол.

    Можете так же сделать бэкап профилей пользователей и восстанавливать их при необходимости.
    Ответ написан
    Комментировать
  • Как найти провод от Nanostation в стойке спд?

    leahch
    @leahch
    3D специалист. Dолго, Dорого, Dерьмово.
    Купите себе Трассоискатель Mastech 13-1220 или аналог. Но тестирует только прямой провод, через коммутатор сигнал не проходит.
    Ну и если коммутатор управляемый, посмотреть таблицу мак-адресов на нем.
    Ответ написан
    7 комментариев
  • Есть ли приглашение в конференцию на Asterisk через кнопки?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    confbridge.conf
    [admin_menu]
    ...
    *#=dialplan_exec(conf-invite,s,1)

    extensions.conf
    [conf-invite]
    exten => s,1,Answer
    same => n,Read(NUMBER,vm-enter-num-to-call)
    same => n,Originate(SIP/${NUMBER},exten,conf-invite,conference,1)
    
    exten => conference,1,Answer
    same => n,ConfBridge(conference,bridge,simple-user,user_menu)
    Ответ написан
  • Порекомендуйте замену vim?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Это решается другим способом. Можно сделать готовый комплект конфигов (не только для vim), который в одну команду заливать на любой новый сервер (например, с помощью ansible). Круче vim всё равно мало что есть (пользуясь случаем, передаю большой привет emacs).
    Ответ написан
    Комментировать
  • Как с помощью awk вставить # в строчку 647?

    xotkot
    @xotkot
    хорошо есть и хорошо весьма
    Как с помощью awk вставить # в строчку 647?

    вставить куда ? начало, конец, посередине ?
    если в начало, то:
    awk -i inplace 'NR==647{print "# "$0}NR!=647' a.txt

    где изменения мы пишем(-i inplace) прямо во входящий файл, в строку(NR) 647, добавляя перед всей строкой($0) решетку с пробелом("# "), при желании можно и без пробела("#"). Остальные строки(NR!=647) мы просто печатаем без изменений.
    Ответ написан
    Комментировать
  • Можно ли использовать open('file','r').read() в python?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Можно вот так делать:
    content = pathlib.Path('file').read_bytes()
    В таком случае всё правильно закроется.
    Вообще нужно стараться уже современные методы работы с файлами и путями использовать, а не доисторические.

    Вы, кстати, самозакрывающуюся читалку и сами сделать можете:
    def readfromfile(filename, mode='t'):
        assert mode in {'b', 't'}
        with open(filename, mode=mode) as f:
            return f.read()

    Но зачем, когда есть замечательный pathlib в третьем питоне из коробки?

    Ну и еще добавлю про незакрытие файлов.
    В продакшн коде, который планирует жить долго, конечно нужно всё правильно закрывать, но если это у вас мелкий одноразовый скрипт, который не открывает миллионов файлов, то вполне можно забить на его закрытие. По завершении процесса (интерпретатора) все его дескрипторы будут высвобождены.
    Ответ написан
    1 комментарий
  • Как после удаления одной записи поменять rowid всех остальных записей в базе данных SQlite3?

    Zoominger
    @Zoominger
    System Integrator
    Не совсем понятно, зачем вам это делать. PRIMARY KEY менять вот так, с бухты-барахты, нельзя, это bad practice.
    Лучше заведите отдельную переменную для этого, какой-нибудь record_id, но тут уже встаёт вопрос производительности - после каждого удаления переписывать всю таблицу не очень хорошо.

    Короче, ответ: задача не имеет корректного решения, исправляйте архитектуру приложения.
    Ответ написан
    Комментировать
  • Какой UI фреймворк использовать для Linux?

    Fragster
    @Fragster
    помогло? отметь решением!
    Ответ написан
    Комментировать
  • Почему зависает вся система при открытии старого форума?

    Может, загружается какой-нибудь крипто-майнер или что-то другое вычислительно тяжелое скриптами JS.
    Может также потребляет много памяти.
    Можно проверить в htop/top.
    Ответ написан
    Комментировать
  • Как правильно декодировать JSON в UnmarshalJSON?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Senior software developer, system architect
    Есть не очень красивый вариант, но если нужно быстро решить задачу - можно использовать.
    Если у вас нагрузка небольшая - можно его использовать на постоянной основе.
    Если же нагрузка огромная - тогда надо иначе делать.
    Только везде, где символ `_` надо сделать обработку ошибок.
    package main
    
    import (
        "encoding/json"
        "fmt"
        "log"
    )
    
    type TemplateCategory struct {
        ID   int    `json:"id"`
        Name string `json:"name"`
    }
    
    type Template struct {
        Name         string            `json:"name"`
        CategoryInfo *TemplateCategory `json:"category_info"`
    }
    
    func (t *Template) UnmarshalJSON(b []byte) error {
        var result map[string]interface{}
        if err := json.Unmarshal(b, &result); err != nil {
            return err
        }
    
        if t == nil {
            t = &Template{}
        }
        t.Name, _ = result[`name`].(string)
    
        categoryInfo, isMap := result[`category_info`].(map[string]interface{})
        if isMap {
            t.CategoryInfo = &TemplateCategory{}
            t.CategoryInfo.ID, _ = categoryInfo[`id`].(int)
            t.CategoryInfo.Name, _ = categoryInfo[`name`].(string)
        }
    
        return nil
    }
    
    func main() {
        json1 := []byte(`{
            "name": "Мой шаблон",
            "category_info": {
                "id": 109,
                "name": "Тест"
            }
        }`)
    
        json2 := []byte(`{
            "name": "Мой шаблон",
            "category_info": []
        }`)
    
        var data1 Template
        err := json.Unmarshal(json1, &data1)
        if err != nil {
            log.Fatalf(`json1: %s`, err)
        }
    
        var data2 Template
        err = json.Unmarshal(json2, &data2)
        if err != nil {
            log.Fatalf(`json2: %s`, err)
        }
    
        fmt.Printf("data1: %+v\n", data1)
        fmt.Printf("data1.CategoryInfo: %+v\n\n", data1.CategoryInfo)
    
        fmt.Printf("\n\ndata2: %+v\n", data2)
        fmt.Printf("data2.CategoryInfo: %+v\n\n", data2.CategoryInfo)
    }

    Вывод:
    data1: {Name:Мой шаблон CategoryInfo:0xc00000c0c0}
    data1.CategoryInfo: &{ID:0 Name:Тест}

    data2: {Name:Мой шаблон CategoryInfo:}
    data2.CategoryInfo:
    Ответ написан
    7 комментариев
  • Как сделать мониторинг в Zabbix множественных параметров через один вызов скрипта?

    @MechanID
    Админ хостинг провайдера
    1 фильтр нужен только если вам нужно работать не со всеми нодами а только с частью по какомуто критерию.
    2 про предобработку и макрос - посмотрите как сделан шаблон "Template Module Linux block devices by Zabbix agent" (у меня уже пятый заббикс но поидее он был такимже и в четвертом) - там берется содержимое файла /proc/diskstats и предобработкой заполняется в массив, после уже дискавери находит нужные блочные устройтва и создает итемы который по имени блочного устройства берут из массива нужное значение.
    Ответ написан
    4 комментария