lrzsz在tmux下并不可用,但有方法取消rz/sz的卡死状态

rz: 5次ctrl+x
sz: 4次ctrl+x

  • ctrl+a: 光标移到行首
  • ctrl+b: 光标左移一个字母
  • ctrl+c: 杀死当前进程
  • ctrl+d: 删除光标所在字母; 注意和backspace以及ctrl+h的区别,这2个是删除光标前的字符
  • ctrl+d: 退出当前 Shell
  • ctrl+e: 光标移到行尾
  • ctrl+f: 光标右移
  • ctrl+h: 删除光标前一个字符,同 backspace 键相同
  • ctrl+k: 清除光标后至行尾的内容
  • ctrl+l: 清屏,相当于clear
  • ctrl+r: 搜索之前打过的命令。会有一个提示,根据你输入的关键字进行搜索bash的history
  • ctrl+t: 交换光标位置前的两个字符
  • ctrl+u: 清除光标前至行首间的所有内容
  • ctrl+w: 移除光标前的一个单词
  • ctrl+y: 粘贴或者恢复上次的删除
  • ctrl+z: 把当前进程转到后台运行,使用fg命令恢复。比如top -d1 然后ctrl+z,到后台,然后fg,重新恢复

源自https://mariadb.com/kb/en/library/group-by/#group-by-examples

Use the GROUP BY clause in a SELECT statement to group rows together that have the same value in one or more column, or the same computed value using expressions with any functions and operators except grouping functions. When you use a GROUP BY clause, you will get a single result row for each group of rows that have the same value for the expression given in GROUP BY.

于是

  1. group by 一个字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
mysql> select count(*), channel from wlan_client group by channel;
+----------+---------+
| count(*) | channel |
+----------+---------+
| 24 | 0 |
| 39767 | 1 |
| 37896 | 6 |
| 48757 | 11 |
| 17398 | 36 |
| 9076 | 40 |
| 13223 | 44 |
| 10594 | 48 |
| 13582 | 52 |
| 5804 | 56 |
| 13966 | 60 |
| 6515 | 64 |
| 19984 | 149 |
| 14560 | 153 |
| 19113 | 157 |
| 21748 | 161 |
| 31 | 165 |
+----------+---------+
17 rows in set (0.41 sec)

这是最常见的操作,没毛病,channel的每一个值都会get a single result row

  1. group by channel > 15
1
2
3
4
5
6
7
8
mysql> select count(*), channel from wlan_client group by channel > 15;
+----------+---------+
| count(*) | channel |
+----------+---------+
| 126444 | 11 |
| 165594 | 44 |
+----------+---------+
2 rows in set (0.41 sec)

说实话我并没有找到有明确的文档说明此用法,但从上面引用的文档原文来看,也能说通,所有channel > 15的被归为了一类,其它的归为更一类,所以结果有两行

可以用简单的count验证

1
2
3
4
5
6
7
mysql> select count(*), channel from wlan_client where channel > 15;
+----------+---------+
| count(*) | channel |
+----------+---------+
| 165594 | 44 |
+----------+---------+
1 row in set (0.30 sec)
  1. group by 整数

You can also use a single integer as the grouping expression. If you use an integer n, the results will be grouped by the nth column in the select expression.

这里是另一种用法,N代表select中的第N项,如上面的select count(), channel from wlan_client group by channel就可写成select count(), channel from wlan_client group by 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
mysql> select count(*), channel from wlan_client group by 2;
+----------+---------+
| count(*) | channel |
+----------+---------+
| 24 | 0 |
| 39767 | 1 |
| 37896 | 6 |
| 48757 | 11 |
| 17398 | 36 |
| 9076 | 40 |
| 13223 | 44 |
| 10594 | 48 |
| 13582 | 52 |
| 5804 | 56 |
| 13966 | 60 |
| 6515 | 64 |
| 19984 | 149 |
| 14560 | 153 |
| 19113 | 157 |
| 21748 | 161 |
| 31 | 165 |
+----------+---------+
17 rows in set (0.40 sec)
  1. group by 1+1 或者 2 > 15

恩,此时mysql不会认为1+1=2,然后同[3], 也不会认为2是channel然后同[2],而是只返回了一条

1
2
3
4
5
6
7
mysql> select count(*), channel from wlan_client group by 2 > 15;
+----------+---------+
| count(*) | channel |
+----------+---------+
| 292038 | 44 |
+----------+---------+
1 row in set (0.30 sec)

这里的count(*)的确是该表的总行数,那么这又是什么意思呢

猜测,这里并没有可以分组的列维度,所以结果应该跟直接count(*)没有group by一样,但既然有group by,又没有找到可以用来计算分组维度的列,mysql竟然没有报错,很是神奇

明明这样是会报错的

1
2
mysql> select count(*), channel from wlan_client group by 0;
ERROR 1054 (42S22): Unknown column '0' in 'group statement'

  1. 在目前macOS Catalina(10.15)上已失效

由于目前的Catalina安全策略

在macOS Catalina中,Apple推出了一种新的文件系统分区结构。新的文件系统分区结构将一个分区作为包含操作系统本身的专用“只读”系统卷,并且与所有用户数据完全分开。除了经过Apple签名的代码(例如:系统更新)之外的任何内容都无法覆盖操作系统文件。这样的机制,基本上使系统完整性保护到达了一个新的水平。现在,整个分区都是封闭的,而不再仅仅是在未受保护的分区中仅仅保护特定位置的内容。

由于在改动后,安装路径不再像之前那么明显,因此可能会存在一些初步的混淆。例如,用户数据位于何处?在此前版本中,用户数据位于/Users/。但在Catalina新版本中,用户数据将位于/System/Volumes/Data/Users/。传统意义上的根目录/,现在将作为一个系统专用的卷。

对于企业来说,最开始要习惯修改后的路径命名约定可能会有一些困难,但从安全性原则上来看,将系统和用户数据的分区之间划分出明确的界限可能是一个良好的举措。这样一来,会使系统恢复和备份变得更加直接。Apple在先前的展示中表示,如果在安装第三方更新后出现问题,macOS Recovery将能够更轻松地从快照恢复。我们可以肯定,这一功能是依赖于新的磁盘分区方案。

/System/Library/LaunchDaemons/ssh.plist 已变的完全不可修改,或者修改方法未知,实测csrutil enable/disable都改不了

  1. 关闭保护机制(System Integrity Protection (SIP))

重启 command + r 进入 Recovery Mode

在终端中输入

1
csrutil disable
  1. 修改ssh.plist
1
vim /System/Library/LaunchDaemons/ssh.plist

1
2
<key>SockServiceName</key>
<string>ssh</string>

把ssh修改为要使用的端口号

1
2
<key>SockServiceName</key>
<string>2333</string>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
:1,10g/{pattern}/{cmd}

:g/{pattern}/d "删除匹配行
:v/{pattern}/d "保留匹配行


:g/{pattern}/m$ "移动匹配行
m0 第一行
m$ 最后一行

:sort
:g/^\(.*\)$\n\1$/d "去除重复行

:sort u "还有这种玩法,为什么不用这种玩法呢

:v/./.,/./-1join "压缩空行
:g/^$/,/./-j "压缩空行

phpMyAdmin用多了不会手写SQL了吧

1
2
3
4
5
6
7
8
9
10
select t.TABLE_NAME
, t.TABLE_ROWS
, round(t.DATA_LENGTH/1024/1024/1024, 2) dataSpace
, round(t.INDEX_LENGTH/1024/1024/1024, 2) indexSpace
, round(sum((t.DATA_LENGTH + t.INDEX_LENGTH)/1024/1024/1024), 2) usedSpace
from information_schema.TABLES t
where t.TABLE_SCHEMA = '数据库名'
group by t.TABLE_NAME
order by usedSpace desc
limit N

IVR

HBSpy: 这里我们综合了IVR, mod_dptools: IVR Menu

About

互动式语音应答(IVR)是一种自动化的电话系统,可以与来话交互以收集信息或按策略路由。

Language

FreeSWITCH IVRs可以用FreeSWITCH支持的任何语言编写,包括JavaScript, Python, Perl, Lua和XML macro格式

Sample IVRs

demo-ivr.xml

源码中自带了一个用XML实现的示例IVR。IVR菜单加载自conf/autoload_configs/ivr.conf.xml

Dialplan调用IVR菜单的入口如下

1
2
3
4
5
<extension name="ivr_demo">
    <condition field="destination_number" expression="5000">
      <action application="ivr" data="demo_ivr"/>
    </condition>
  </extension>

IVR Macro文件位于conf/lang/en/demo/demo-ivr.xml

mod_dptools: IVR Menu

IVR Menu功能可以使你简单的用XML描述IVR菜单o

菜单定义在配置文件autoload_configs/ivr.conf.xml中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<configuration name="ivr.conf" description="IVR menus">
<menus>
<!-- demo IVR setup -->
<!-- demo IVR, Main Menu -->
<menu name="demo_ivr"
greet-long="phrase:demo_ivr_main_menu"
greet-short="phrase:demo_ivr_main_menu_short"
invalid-sound="ivr/ivr-that_was_an_invalid_entry.wav"
exit-sound="voicemail/vm-goodbye.wav"
timeout ="10000"
inter-digit-timeout="2000"
max-failures="3"
digit-len="4">
<entry action="menu-exec-app" digits="1" param="bridge sofia/$${domain}/[email protected]"/>
<entry action="menu-exec-app" digits="2" param="transfer 9996 XML default"/> <!-- FS echo -->
<entry action="menu-exec-app" digits="3" param="transfer 9999 XML default"/> <!-- MOH -->
<entry action="menu-sub" digits="4" param="demo_ivr_submenu"/> <!-- demo sub menu -->
<entry action="menu-exec-app" digits="5" param="transfer 1234*256 enum"/> <!-- Screaming monkeys -->
<entry action="menu-exec-app" digits="/^(10[01][0-9])$/" param="transfer $1 XML default"/> <!-- dial ext & x-fer -->
<entry action="menu-top" digits="9"/> <!-- Repeat this menu -->
</menu>
<!-- Demo IVR, Sub Menu -->
<menu name="demo_ivr_submenu"
greet-long="phrase:demo_ivr_sub_menu"
greet-short="phrase:demo_ivr_sub_menu_short"
invalid-sound="ivr/ivr-that_was_an_invalid_entry.wav"
exit-sound="voicemail/vm-goodbye.wav"
timeout="15000"
max-failures="3">
<entry action="menu-top" digits="*"/>
</menu>
</menus>
</configuration>

IVR Menu支持使用phrase macro。在phrase后写phrase macro的macro名字即可。务必保证tts-engine, tts-voice和phrase-lang被正确设置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<menu name="main"
greet-long="phrase:mainmenu_phrase_macro"
greet-short="phrase:short_mainmenu_phrase_macro"
invalid-sound="phrase:invalid_entry_macro"
exit-sound="phrase:goodbye_macro"
timeout ="10000"
max-failures="3"
tts-engine="cepstral"
tts-voice="david"
phrase_lang="en">
<entry action="menu-exit" digits="*"/>
<entry action="menu-sub" digits="2" param="menu2"/>
<entry action="menu-say-phrase" digits="4" param="enteraccount"/>
<entry action="menu-back" digits="5"/>
<entry action="menu-exec-app" digits="7" param="transfer 888 XML default"/>
<entry action="menu-sub" digits="8" param="menu8"/>
</menu>

有时需要在来话进入IVR应用之前添加如下内容,以保证之不在early media阶段被接听

1
<action application="answer"/>

Options

菜单选项

  • name - IVR菜单名称
  • greet-long - 当菜单首次播放时的内容,可以是个文件或者"say:文本"或者"phrase:phrase_marco名"
  • greet-short - 当菜单循环时播放的短一些的内容,可以是文件,say,phrase
  • invalid-sound - 无菜单入口或入口非法时播放的内容,
  • exit-sound - 菜单退出时播放的内容,可以是文件,say,phrase
  • inter-digit-timeout - 等待用户进行选择的毫秒数
  • timeout - 在confirm-macro播放后等待用户按确认键的毫秒数
  • confirm-macro -
  • confirm-key - 按个键告诉IVR digit-entry输完了。默认为#
  • confirm-attempts -
  • max-failures - 在IVR结束之前的最大digit-entry失败次数
  • max-timeouts - 在IVR结束之前的最大超时次数
  • exec-on-max-failures - max-failures时执行的FreeSWITCH dialplan应用
  • exec-on-max-timeouts - max-timeouts时执行的FreeSWITCH dialplan应用
  • tts-engine - TTS引擎名
  • tts-voice - TTS播音员名
  • digit-len - 在匹配菜单入口前等待的最长位数

每个菜单支持通过按键绑定一系列动作

  • menu-exit - 退出IVR菜单
  • menu-sub - 进入IVR子菜单
  • menu-exec-app - 执行一个FreeSWITCH dialplan应用
  • menu-play-sound - 播放声音文件或speak
1
2
<entry action="menu-play-sound" digits="3" param="say: You pressed 3"/>
<entry action="menu-play-sound" digits="6" param="voicemail/vm-goodbye.wav"/>
  • menu-back - 回到上一级菜单
  • menu-top - 回到顶级菜单
  • menu-exec-api目前一直没实现

Hexo 3.8.0 渲染 Markdown Footnotes 不能问题

Try:

1
2
npm remove hexo-renderer-marked --save
npm install hexo-renderer-markdown-it-plus --save

mod_curl

About

这个应用可以让你在dialplan中做HTTP请求并接收返回。返回可以是plain text或json对象

Setup & Configuration

为了使用mod_curl,你可以通过编辑modules.conf,去掉对应的注释来编译此模块

1
#applications/mod_curl

重新编译FreeSWITCH

1
2
make
make install

HBSpy: 这里应该不需要这么麻烦,去掉注释后 make mod_curl-install 即可

编辑/usr/local/freeswitch/conf/autoload_configs/modules.conf使该模块在启动时加载

1
<load module="mod_curl"/>

此模块没有其它单独的配置文件

mod_curl提供了以下两个功能的API和dialplan APP

  • curl - 可以用之向WEB服务器发起任意的请求
  • curl_sendfile - 可以用之向WEB服务器/REST传输任意长数据,并接收可选返回

Application

curl APP的语法是这样的

1
<action application="curl" data="url [headers|json] [get|head|post [url_encode_data]]"/>

curl APP会设置curl_response_data和curl_response_code两个变量。如果需要,curl_response_data也可以是headers/body或者json的

1
2
3
4
5
6
<action application="curl" data="http://www.google.com"/>
<action application="info"/>
<action application="curl" data="http://www.google.com headers"/>
<action application="info"/>
<action application="curl" data="http://www.google.com json"/>
<action application="info"/>

curl_sendfile有如下两种语法

1
<action application="curl_sendfile" data="<url> <filename_post_name=/path/to/filename [nopost|foo1=bar1&foo2=bar2&...fooN=barN [event|none [uuid|identifier]]]"/>

或者像这样使用通道变量

1
2
3
4
5
6
7
<action application="set" data="curl_sendfile_report=event"/>
<action application="set" data="curl_sendfile_url=http://www.mydomain.com/test_files.php"/>
<action application="set" data="curl_sendfile_filename_element=myFile"/>
<action application="set" data="curl_sendfile_filename=/tmp/somefile.dmp"/>
<action application="set" data="curl_sendfile_extrapost=foo1=bar1&foo2=bar2&testing=a%20pain%20in%20the%20rear"/>
<action application="set" data="curl_sendfile_identifier=1234567890"/>
<action application="curl_sendfile"/>

url, filename, extrapost这些通道变量需要urlencode,data="“字段也是。如果调用此APP时,在data=”"字段里提供了全部的请求参数,你必须指定’nopost’来继续使用data line中其它的参数。如果你指定’uuid’作为identifier,此APP会自动的使用此session的uuid作为这个值。

HBSpy: 'nopost’这里的意思是说要使用[event|none [uuid|identifier]]啥的就不能让前面这儿空着,如果没有请求参数就写nopost。感觉是个常识

CLI / API

在CLI中调用此API,语法是这样的

1
curl url [headers|json|content-type <mime-type>|connect-timeout <seconds>|timeout <seconds>] [get|head|post|delete|put [data]]
1
[api/bgapi] curl_sendfile <url> <filenameParamName=filepath> [nopost|postparam1=foo&postparam2=bar... [event|stream|both|none  [identifier ]]]

HBSpy: 原文中的这些例子就忽略了,都比较简单

总结

如果你不喜欢ESL,或是需要与CTI交互的信息不多,那么mod_curl就是一个非常好的方式

把IVR与mod_curl相结合,就可以写出简单的自助信息查询等功能了

如果使用ESL,那么其实并不建议与ESL混用,在FS中想实现一个功能通常有许多种方式,在一个项目中使用统一的方式通常能够带来维护上的便利。

FreeSWTICH非权威指南

目标

出于公司要开发呼叫中心相关业务被迫学习了FreeSWITCH orz

然而似乎软交换这东西并不怎么火热,中文的参考资料似乎只有杜金房(Seven Du)
老师的《FreeSWITCH权威指南》以下简称《权威》

官方文档写的凑合,但是一些细节交待的也不清不楚

出于为日后接手此项目的人员能在两周内快速上手,故逐步丰富该系列文档,主要形式是项目中使用或可能使用到的功能,给官方文档的做个翻译,并且加入一些个人的见解。

目前的见解大多是实践所得,并没有进行源码解析

环境

  • Linux: HBSpy.NMS-NG 3.10.0-957.5.1.el7.x86_64 #1 SMP Fri Feb 1 14:54:57 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
  • FreeSWITCH: Version 1.9.0+git20190117T172020Zeb37939b5c~64bit (git eb37939 2019-01-17 17:20:20Z 64bit)

TODO

  • [x] mod_fifo
  • [x] mod_curl
  • [ ] mod_xml_curl
  • [ ] IVR
0%