FreeSwitch数据库

2023-10-26

Freeswitch数据库

一、ODBC DSN

1.概念

ODBC:

开放数据库连接(Open Database Connectivity,[ODBC](https://baike.baidu.com/item/ODBC))是为解决异构数据库间的数据共享而产生的,基于Windows环境的一种数据库访问接口标准ODBC 为异构数据库访问提供统一接口,允许应用程序以SQL 为数据存取标准,存取不同DBMS管理的数据;使应用程序直接操纵DB中的数据,免除随DB的改变而改变。用ODBC 可以访问各类计算机上的DB文件,甚至访问如Excel 表和ASCI I数据文件这类非数据库对象。

DNS

Data Source Name (DSN) [1]  的PDO命名惯例为:PDO驱动程序的名称,后面为一个冒号,再后面是可选的驱动程序连接数据库变量信息,如主机名、端口和数据库名。

例子:

DSN with username and password
<param name="core-db-dsn" value="database:username:password"/>

or

<param name="core-db-dsn" value="odbc://database:username:password"/>
DSN with username
<param name="core-db-dsn" value="database:username:"/>

or

<param name="core-db-dsn" value="odbc://database:username"/>
DSN only
<param name="core-db-dsn" value="database::"/>

or

<param name="core-db-dsn" value="odbc://database"/>
DSN-less

(懒加载,不需要再odbc.ini中配置数据源)

<param name="core-db-dsn" value="odbc://DRIVER=mysql;SERVER=a.b.c.d;UID=username;PWD=secretpassword;DATABASE=freeswitch;OPTION=67108864">

1.核心数据库使用ODBC

使用之前 请确保你linux上已经安装mysql或其他数据库,和ODBC驱动

软件要求:

unixODBC >= 2.3
数据库ODBC驱动

安装 unixODBC

sudo apt-get install unixodbc-dev

安装unixODBC驱动

MySQL:

`sudo apt-get install libmyodbc`

PostgreSQL

`sudo apt-get install odbc-postgresql`

修改odbc配置文件

Mysql: /etc/odbc.ini

[freeswitch]
Driver = /usr/lib64/odbc/libmyodbc.so  
SERVER = localhost
PORT = 3306
DATABASE = freeswitch 
USER = root 
PASSWORD = password
Socket = /var/lib/mysql/mysql.sock       //这行只针对本地,远程链接数据库请删除这行

OPTION = 67108864 //可加可不加,参考“网址1”,

网址1:

http://dev.mysql.com/doc/refman/5.0/en/connector-odbc-configuration-connection-parameters.html

注意**:如果你安装的是32为的操作系统 那么这这块驱动路径改成:

/usr/lib64/ 改成 /usr/lib/

Mysql : /etc/odbcinst.ini

[MySQL]
Description = MySQL driver
Driver = /usr/lib64/odbc/libmyodbc.so
Setup = /usr/lib64/odbc/libodbcmyS.so
UsageCount = 1
FileUsage = 1
Threading = 0

注意:如果你电脑上有这个 /usr/lib64/odbc/libmyodbc**_r**.so 驱动 那你必须使用这个

每修改odbcinst.ini,重启freeswitch生效

PostgreSQL : /etc/odbc.ini

[freeswitch]
; WARNING: The old psql odbc driver psqlodbc.so is now renamed psqlodbcw.so
; in version 08.x. Note that the library can also be installed under an other
; path than /usr/local/lib/ following your installation.
Driver = /usr/lib64/odbc/psqlodbcw.so
Description=Connection to LDAP/POSTGRESQL
Servername=localhost 
Port=5432 
Protocol=6.4
FetchBufferSize=99
Username=postgres 
Password=password 
Database=freeswitch 
ReadOnly=no
Debug=0
CommLog=0

注意:如果你安装的是32为的操作系统 那么这这块驱动路径改成:

/usr/lib64/ 改成 /usr/lib/

PostgreSQL : /etc/odbcinst.ini

[PostgreSQL]
Description = PostgreSQL driver for Linux & Win64
Driver = /usr/lib64/odbc/psqlodbcw.so

验证链接是否成功

常用命令:

odbcinst -j      //查看本机安装odbc驱动版本信息
odbcinst -q -d    //查看odbc ini配置文件配置数据库是否成功
isql -v freeswitch   //验证odbc链接名字为freeswitch的链接是否成功

安装mysql odbc数据库驱动

yum install unixODBC-devel mysql-connector-odbc

创建数据库

注意不要使用utf8_bin编码,尤其ip配置
mysql 修改数据库密码:
UPDATE mysql.user
SET password=OLD_PASSWORD('somepassword')
WHERE user='someuser'
AND host='somehost';
编译freeswitch+odbc
./configure
如果ODBC不可用

尝试把odbc驱动拷贝到freeswitch目录

mkdir /usr/local/freeswitch/etc
ln -s /etc/odbcinst.ini /usr/local/freeswitch/etc/odbcinst.ini
ln -s /etc/odbc.ini /usr/local/freeswitch/etc/odbc.ini

二、使用lua脚本连接

1.连接数据库

连接数据库方式:
 Lua: LuaSQL  /可以使用ODBC连接PostgreSQL、Oracle、or MySQL等数据库
 freeswitch.Dbh   //推荐

推荐使用freeswitch.Dbh,因为它使用数据库连接池,高效处理速度。

LuaSQL

官网:

http://keplerproject.org/luasql/

样例:

--  this example of how to connect to postgres from Lua
local luasql = require "luasql.postgres"
--
-- Database connection settings
--
DBHOST = '127.0.0.1'
DBNAME = 'dbname'
DBUSER = 'dbusername'
DBPASS = 'dbpassword'
DBPORT = 5432
 
local env = assert (luasql.postgres())
local dbcon = env:connect(DBNAME, DBUSER, DBPASS, DBHOST, DBPORT)
sql = 'SELECT pin, name FROM customer'
res, serr = dbcon:execute(sql)
dbcon:close()
env:close()
freeswitch.Dbh

相较于TCP连接访问数据库、LuaSQL env:connect(), freeswitch.Dbh在使用数据库连接池在数据库读写速度上有明显提高

local dbh = freeswitch.Dbh("dsn","user","pass") --ODBC
-- or --
local dbh = freeswitch.Dbh("core:my_db") -- sqlite
-- or --
local dbh = freeswitch.Dbh("sqlite://my_db") -- sqlite
-- or --
local dbh = freeswitch.Dbh("odbc://my_db:uname:passwd") --连接odbc数据库
 
assert(dbh:connected()) --判断数据库是否连接成功
 
dbh:test_reactive("SELECT * FROM my_table",
                  "DROP TABLE my_table",
                  "CREATE TABLE my_table (id INTEGER(8), name VARCHAR(255))")
 
dbh:query("INSERT INTO my_table VALUES(1, 'foo')") --查询语句
dbh:query("INSERT INTO my_table VALUES(2, 'bar')") --查询语句
 
dbh:query("SELECT id, name FROM my_table", function(row)
  stream:write(string.format("%5s : %s\n", row.id, row.name))
end)
 
dbh:query("UPDATE my_table SET name = 'changed'")
stream:write("Affected rows: " .. dbh:affected_rows() .. "\n")
 
dbh:release() -- 释放关闭数据库连接
  • freeswitch.Dbh(odbc://my_db:uname:passwd) 获取ODBC数据库连接池

  • freeswitch.Dbh(“sqlite://my_db”) 获取核心数据库连接池,如果不存在数据库则创建

  • dbh:connected() 数据量连接返回true,否则返回false

  • dbh:test_reactive(“test_sql”, “drop_sql”, “reactive_sql”) 执行test_sql 且如果失败则执行drop_sql 和 reactive_sql

    1

样例

--  this is an example of how to connect to Postgres using ODBC from Lua
local dbh = freeswitch.Dbh("odbc://my_db:uname:passwd") -- connect to ODBC database 
assert(dbh:connected()) -- exits the script if we didn't connect properly
dbh:query("SELECT pin, name FROM customer", function(row)
  stream:write(string.format("%5s : %s\n", row.id, row.name))
end)
dbh:release() -- optional

三、FreeSwitch数据库整合lua

本示例展示的是如何从数据库地区变量值,并将其设置成Freeswitch通道变量

假使你有一个did_users数据库表,这个表有两列数据 did和user和主键

1.拨号计划XML Dialplan

<extension name="map_did_to_user" continue="true">
  <condition field="destination_number" expression="^(\+|00)(\d+)$">
    <action inline="true" application="lua" data="map_did_to_user.lua $2"/>
  </condition>
</extension>

<extension name="if_user_then_">
  <condition field="${user}" expression="...

data="map_did_to_user.lua指向lua脚本

注意:

  • the lua script must be run inline, so that the retrieved channel variables are available immediately.
lua脚本必须以关键字运行,以产生channel变量
  • C++关键字,在函数声明或定义中函数返回类型前加上关键字inline,即可以把函数指定为内联函数。关键字inline必须与函数定义放在一起才能使函数成为内联,仅仅将inline放在函数声明前面不起任何作用。inline是一种"用于实现的关键字",而不是一种"用于声明的关键字"。一般的,用户可以阅读函数的声明,但是看不到函数的定义

2.lua脚本 Lua Script

map_did_to_user.lua

-- map_did_to_user.lua
-- takes DID as first argument

local did = argv[1]

local dbh = freeswitch.Dbh("odbc://datasourcename:username:password")

local function set_session_variables(row)
  -- Sets session variables with the same names as the columns from the database
  for key, val in pairs(row) do
    if session then
      session:setVariable(key, val)
    end
    freeswitch.consoleLog("DEBUG", string.format("set(%s=%s)\n", key, val))
  end
end

assert(dbh:connected())

local sql_query = "SELECT user FROM did_users WHERE did = " .. did

assert(dbh:query(sql_query, set_session_variables))
  • The script checks if a session is available. If it is, the key/value will be set as a channel variable. The result will always be printed to your console in the debug level.

    脚本检查session是否存在,如果存在则将key/value设置成通道变量,结果会打印在debug级别的console日志控制台
    

3.User目录XML

  • 该脚本从FreeSwitch使用SQL查询User目录XML文件
  • 假使你数据库有一张表users,含有以下字段domain, id, mailbox, number-alias, password, dial-string and user_context (all varchars).
Lua配置

lua.conf.xml

<param name="xml-handler-script" value="gen_dir_user_xml.lua"/>
<param name="xml-handler-bindings" value="directory"/>
Mysql样例
-- gen_dir_user_xml.lua
-- example script for generating user directory XML

-- comment the following line for production:
freeswitch.consoleLog("notice", "Debug from gen_dir_user_xml.lua, provided params:\n" .. params:serialize() .. "\n")

local req_domain = params:getHeader("domain")
local req_key    = params:getHeader("key")
local req_user   = params:getHeader("user")

assert (req_domain and req_key and req_user,
  "This example script only supports generating directory xml for a single user !\n")

local dbh = freeswitch.Dbh("odbc://datasourcename:username:password")
if dbh:connected() == false then
  freeswitch.consoleLog("notice", "gen_dir_user_xml.lua cannot connect to database" .. dsn .. "\n")
  return
end

-- it's probably wise to sanitize input to avoid SQL injections !
local my_query = string.format("select * from users where domain = '%s' and `%s`='%s' limit 1",
  req_domain, req_key, req_user)

assert (dbh:query(my_query, function(u) -- there will be only 0 or 1 iteration (limit 1)
  XML_STRING =
[[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="freeswitch/xml">
  <section name="directory">
    <domain name="]] .. u.domain .. [[">
      <user id="]] .. u.id .. [[" mailbox="]] .. u.mailbox .. [[" cidr="]]
           .. u.cidr .. [[" number-alias="]] .. u["number-alias"] .. [[">
        <params>
          <param name="password" value="]] .. u.password .. [["/>
          <param name="dial-string" value="]] .. u["dial-string"] .. [["/>
        </params>
        <variables>
          <variable name="user_context" value="]] .. u.user_context .. [["/>
        </variables>
      </user>
    </domain>
  </section>
</document>]]

  -- comment the following line for production:
  freeswitch.consoleLog("notice", "Debug from gen_dir_user_xml.lua, generated XML:\n" .. XML_STRING .. "\n")
end))
db_connect.lua rewrite
-- db_connect.lua
-- Connects to a database using freeswitch.Dbh connection pooling, checks PIN, reads balance
-- A hangup function makes the code a bit cleaner

local dbh = freeswitch.Dbh("odbc://datasourcename:username:password")
local row = {}

function hangup_call ()
    session:streamFile("ivr/ivr-thank_you.wav")
    session:sleep(250)
    session:streamFile("voicemail/vm-goodbye.wav")
    session:hangup()
end

if dbh:connected() == false then
   freeswitch.consoleLog("notice", "gen_dir_user_xml.lua cannot connect to database" .. dsn .. "\n")
   hangup_call()  
end

-- Set invalid entry file
invalid = "ivr/ivr-that_was_an_invalid_entry.wav"

-- Greet caller
session:answer()
session:streamFile("ivr/ivr-hello.wav")
tries = 0

while (tries < 3) do
-- Collect account number
    acct = session:playAndGetDigits(3, 5, 3, 7000, "#", "phrase:enter_message_number", invalid, ".+")
    if (acct) then
        -- Pull account from database -> assumes that acct is unique
        my_query = "select * from users where acct = " .. acct
        assert(dbh:query(my_query, function(qrow)
        for key, val in pairs(qrow) do
            row[key] = val
        end
        end))
    end
    -- Confirm that we received the record
    if (row.pin ~= nil) then
        -- We have an account, now collect PIN and check
        tries = 0
        while (tries < 3) do
            pin = session:playAndGetDigits(3, 5, 3, 7000, "#", "ivr/ivr-please_enter_pin_followed_by_pound.wav", invalid, "\\d+")
            if (row.pin == pin) then
                user_repeat = true
                while(user_repeat == true) do
                    session:streamFile("voicemail/vm-you_have.wav")
                    session:sleep(200)
                    session:say(row.balance, "en", "currency", "pronounced")
                    session:sleep(200)
                    -- "to repeat these options, please press 1"    
                    digits = session:playAndGetDigits(1,1,3,7000,"#",
                      "file_string://ivr/ivr-to_repeat_these_options.wav!ivr/ivr-please.wav!voicemail/vm-press.wav!digits/1.wav", 
                                invalid,"\\d+") 
                    -- repeat y/n
                    freeswitch.consoleLog("INFO","User entered '" .. digits .. "'\n")
                    if (digits == "1") then
                        user_repeat = true
                    else
                        hangup_call()
                        break
                    end
                end
            else
                -- Callerr entered wrong PIN
                session:streamFile("ivr/ivr-that_was_an_invalid_entry.wav")
                tries = tries + 1;
            end
        end
        if (tries > 2) then
            -- Too many failed attempts to enter PIN
            session:streamFile("voicemail/vm-abort.wav")
            hangup_call()
            break
        end
    else
        -- We did not find this account
        session:streamFile(invalid)
        tries = tries + 1;
    end
end -- while (tries < 3)

if (tries > 2) then
    session:streamFile("voicemail/vm-abort.wav")
    hangup_call()
end

四、FreeSwitch数据库

  • 默认FreeSwitch配置使用一系列SQlite数据库配置 /usr/local/freeswitch/db
  • FreeSWITCH核心提供API结构供其他模块连接到数据库,
  • DSN XML配置文件中定义数据源例如: “core-db-dsn”, “odbc-dsn”, 等
[root@localhost db]# ls
call_limit.db  core.db  fifo.db  json.db  sofia_reg_external.db  sofia_reg_external-ipv6.db  sofia_reg_internal.db  sofia_reg_internal-ipv6.db  voicemail_default.db

1.常用格式

  • DSN格式

    <type>://<connection string>
    
  • SQLite DSNs

    sqlite://filename
    sqlite:///usr/local/freeswitch/db/mega.db
    
  • PostgreSQL DSNs

    pgsql://hostaddr=127.0.0.1 dbname=freeswitch user=freeswitch password= options='-c client_min_messages=NOTICE' application_name='freeswitch'"
    
  • ODBC DSNs

    <param name="core-db-dsn" value="database:username:password"/>
    

    or

    <param name="core-db-dsn" value="odbc://database:username:password"/>
    

    DSN with username

    <param name="core-db-dsn" value="database:username:"/>
    

    or

    <param name="core-db-dsn" value="odbc://database"/>
    

    DSN-less

    <param name="core-db-dsn" value="odbc://DRIVER=mysql;SERVER=a.b.c.d;UID=username;PWD=secretpassword;DATABASE=freeswitch;OPTION=67108864">
    

2.FreeSwitch使用数据库模块

3.FreeSwitch配置数据库

  • 核心

conf/autoload_configs/switch.conf.xml

<param name="core-db-dsn" value="odbc://tuxza:admin:pass" />

or

<param name="odbc-dsn" value="odbc://your_dsn_name:your_db_user:your_db_password"/>
  • recovery

switch.conf.xml

<param name="core-recovery-db-dsn" value="odbc://your_dsn_name:your_db_user:your_db_password"/>
  • mod_sofia

sofia.conf.xml

sip_profiles/external.xml
sip_profiles/internal.xml
sip_profiles/internal-ipv6.xml
  • mod_limit

    db.conf.xml

  • mod_voicemail

    voicemail.conf.xml

  • mod_lcr

    lcr.conf.xml

  • mod_nibblebill

    nibblebill.conf.xml

五、ODBC Methods

1.ODBC.connect

  • 样例
use("ODBC");
var db = new ODBC("dsnName", "username", "password");
db.connect();
  • Return value

    true - 连接成功

    false - 连接失败

2.ODBC.execute

  • 样例
use("ODBC"); 
var db = new ODBC("dsnName", "username", "password");
var sql="delete from users";
db.execute(sql);
  • return value
boolean - true  连接成功

3.ODBC.getData

  • 样例
var row = db.getData();
console_log("notice",row["my_field"]+"\n");
  • return value
返回值array

4.ODBC.nextRow

  • 样例
result = db.nextRow();

在getData前调用

  • return value
boolean - true  表示有下一行数据

5.ODBC.query

  • 样例
var row, result;
result = db.query("sql statement");
while (db.nextRow()) {
   row = db.getData();
   console_log("Row[0]: " + row[0] + "\n");
}

5.ODBC.close

  • 样例
db.close();

example1

//Simple Example
use("ODBC");
var DSN = "test_odbc";
var DB_USER = "abc";
var DB_PASS = "abc";
var db = new ODBC(DSN, DB_USER, DB_PASS);
db.connect();
//Do something with our database connection.
db.close();

example2

//Example of opening a connection more than once in your script.
var db = new ODBC(DSN, DB_USER, DB_PASS);
db.connect();
//Do something...
db.close();
db = new ODBC(DSN, DB_USER, DB_PASS);
db.connect();
//Do something...
db.close();

6.使用ODBC模块

<load module="mod_spidermonkey_odbc"/>

六、虚拟机安装centos+freeswitch

注意:由于公司网络限制及操作系统限制,在安装本软件的过程中会出现很多问题

需要先解决的问题:

1.网络问题   由于公司网络限制,即使在正确配置虚拟机网络设置的情况下,在主机和宿主机相互都可以ping通的前提下,任然无法上网,可以采用一下方法解决
a.在自己电脑上下载相关文件,传到公司电脑。
b.公司电脑连接自己手机热点下载(在这种情况下,在下载freeswitch过程中由于现在速度过慢可以选择从主机端下载,通过xftp传到宿主电脑,然后进行解压安装等操作)

1.软件要求

  • wmware
VMware® Workstation 15 Pro(破解码网上有很多)
  • centOS 6 64
CentOS-6.6-x86_64-bin-DVD1.iso
  • FreeSwitch
freeswitch-1.6.6.tar.gz
网址:https://files.freeswitch.org/freeswitch-releases/
这个对方推荐直接从该网址进行下载,通过ftp传到宿主电脑,这样下载速度快一些
  • Xmanager Power Suite 6
下载地址:https://www.newasp.net/soft/467373.html
破解:
用户名:newasp
公司名称:newasp
序列号:181030-116246-999646
使用xshell   xftp插件和宿主机进行交互

freeswitch下载地址:

https://files.freeswitch.org/freeswitch-releases/
  • mysql-connector-odbc.x86_64
contOS6  数据库odbc连接驱动
  • mysql-server.x86_64
centOS6   mysql数据库连接程序

2.安装虚拟机

安装步骤

点击 “文件”–》新建虚拟机–》典型–》下一步

1572853300206

点击浏览 ,这个地方选择前文所说下载好的centOS6的iso安装包,然后下一步

1572853381093

然后输入系统登录账户和密码,这个地方的设置类似于windows系统锁屏之后的账户和密码,和centOS系统内部root账户和密码无关。centOS系统内部账户和密码等会单独设置。

1572853628667

系统名称:vmware 打开界面之后点击该名称可以切换到系统启动页面

位置:这个位置很重要,一定要记住。最好放到不容易被删除的地方。如果向拷贝虚拟机系统镜像的话,直接蒋该文件夹下面和刚才新建的系统名称 相关文件全部打包拷贝至其他电脑上,就可以使用vmware直接打开克隆之后的系统

1572853792483

最大磁盘大小:这个可以设置大一点,不是立马生效的,类似与系统最大硬盘容量

1572853966433

点击下一步,之后即可完成虚拟系统的创建。

1572854061702

点击 “开启此虚拟机”。

1572854152870

至此,如果你出现下图的报错提示信息,说明你的电脑系统bios设置了禁用vitural machine。怎么办?联系桌面运维,将系统bios设置里面的带有 …vitural machine相关字眼的选项设置成enable(因为咱们自己没有权限啦,不能改,要装机密码的,所以就去找人家吧)

1572854208432

完成上一步之后,你就可以开始安装你刚才配置的centOS6的镜像了。

centOS6镜像的安装这个地方就不说了,有一点得提醒一下

系统账户密码,这个得设置
网络这个也得设置

假设你已经安装完成了centOS系统,而且可以正常登陆,那么进行系统第一件事情就是ping

ping -b www.baidu.com  //查看是否可以上网
ping 你的主机ip    //如果ping不通,返回虚拟机安装步骤 单独对虚拟机进行设置

如何查看自己的虚拟机的宿主机子ip,命令行: ip a ,下文中的

[root@localhost etc]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:7f:8a:a9 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.132/24 brd 192.168.122.255 scope global eth0
    inet6 fe80::20c:29ff:fe7f:8aa9/64 scope link 
       valid_lft forever preferred_lft forever
[root@localhost etc]# 

eth0:虚拟网卡名称
inet 192.168.122.132  //你的虚拟机的ip地址

如何知道宿主机的ip?

上文一级知道自己虚拟机的ip地址,那么在下图中看网段192.168.122,我的是

VMnet8     这个是我现在用的虚拟网卡的名称
192.168.122.0   这个就是我的宿主机的ip地址

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UAVfmd0N-1573810445166)(D:\Users\chenyj91\AppData\Roaming\Typora\typora-user-images\1572854693511.png)]

好了,回到之前ping 的步骤,ping宿主机

ping 192.168.122.0

如果可以通,那么ok,如果不通

service iptables stop/start   关闭/启动防火墙
这里关闭防火墙 ,然后再ping

宿主机子ping虚拟机,如果不通那么关闭宿主机防火墙

ping 192.168.122.132

在确保之前步骤都执行通的前提下 再做下文。

修改centOS6系统root用户权限

cd etc
ls
vi sudoers
找到自己注册的账户名称的那一行,将第一个500,改成0
后文,打开root权限只需要:
		[chen@localhost Desktop]$ su
		Password: 
		[root@localhost Desktop]# 

注意:这里如果你开通root权限,下文中使用xftp传文件的时候会显示没有权限。

3,安装Xmanager

安装步骤这里不说,一路下一步,激活环节参照上文注册码及用户名

这里只说链接虚拟机的配置,以xftp为例:

端口:22
主机:这个地方是你的虚拟机的ip地址
其他

1572855405525

传文件的界面如下

1572856591747

至此,假设你已经完成上文所有步骤,且验证正确。

4.文件下载

freeswitch文件下载,选择下载xxx.tar.gz的1.6的压缩包

https://files.freeswitch.org/freeswitch-releases/

在windows系统上下载好之后通过ftp传至linux系统

or

命令行下载(这种方式很慢)

$ sudo yum install epel-release vim -y
$ curl -O  http://files.freeswitch.org/freeswitch-releases/freeswitch-1.6.6.tar.bz2
$ sudo yum install bzip2 -y
$ tar xvjf freeswitch-1.6.6.tar.bz2

安装系统需要的插件

sudo yum install gcc-c++ sqlite-devel zlib-devel libcurl-devel pcre-devel  speex-devel ldns-devel  libedit-devel  openssl-devel epel-release vim  bzip2 -y

$ sudo yum install libjpeg-devel lua-devel libsndfile-devel libyuv-devel git libtool -y


如果你是下载的xxx.tar.gz格式的文件,则自己解压,至于文件存放路径自己创建

这里我默认的传到/根目录

[root@localhost /]#tar zxvf freeswitch-1.6.6.tar.gz

解压完成之后

[root@localhost /]# cd freeswitch-1.6.6
[root@localhost /]# ls    //查看相关文件

安装freeswitch

  • ./configure
[root@localhost freeswitch-1.6.6]# ./configure   //如果报错  先解决报错,然后再执行这个命令,直到不报错,此版本本命令不报错
  • make
如果在make的过程中报错停止,请在命令行输入
[root@localhost freeswitch-1.6.6]# vi modules.conf   注释掉相关的模块即可,然后重复make命令
如果make命令执行完之后出现freeswitch图标,则表示make完成
至此,make install是不会报错的,make install 完成之后还是会出现freeswitch图标

启动freeswitch

  • 默认安装位置
[root@localhost local]# cd /usr/local/freeswitch/
[root@localhost bin]# ./freeswitch   //启动

安装mysql及MySQ odbc

[root@localhost bin]# yum search mysql  //找到mysql-connector-odbc.x86_64和mysql-server.x86_64  分别执行yum install xxx进行安装
[root@localhost bin]# yum search odbc   //找到unixODBC.x86_64 ,俺也和上面一样安装

5.创建freeswitch_db表

mysql常用命令:

查看是否安装了mysql数据库:rpm -qa | grep mysql

强制卸载mysql数据库:rpm -e nodeps mysql

通过命令查看yum上提供的数据库可下载版本:yum list | grep mysql

安装数据库:  yum -y install mysql-server mysql-devel

启动数据库:  service mysqld start
                                                                                   
查看是否是开机启动(若2~5都是on则表明是开机启动):

chkconfig --list | grep mysqld

若2~5都是off则用以下命令设置:  chkconfig mysqld on 

chkconfig --list | grep mysqld

启动mysql: service mysqld start

设置用户及密码(输入以下命令后两次回车,及第一次密码直接回车即可): mysqladmin -u root -p password 'root'

测试登录mysql:  mysql -u root -p

停止数据库  service mysqld  stop    

6.修改ODBC桥接驱动脚本

常用命令

[root@localhost bin]#odbcinst -j   //这个地方主要看配置文件路径和驱动地址
[root@localhost bin]# odbc -q -d    //查看odbcinst.ini文件配置成功的数据库连接名称
[root@localhost bin]#isql -v freeswitch root root   //执行该命令查看odbc.ini文件中配置的数据库名称为freeswitch,账户和密码为 root root 的数据库数据库连接是否成功
[root@localhost etc]# odbcinst -j
unixODBC 2.3.7
DRIVERS............: /usr/local/etc/odbcinst.ini   //下文中要修改的文件地址
SYSTEM DATA SOURCES: /usr/local/etc/odbc.ini        //下文中要修改的文件地址
FILE DATA SOURCES..: /usr/local/etc/ODBCDataSources
USER DATA SOURCES..: /root/.odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8

  • odbcinst.ini
[MySQL]
Description = MySQL driver
Driver = /usr/lib64/libmyodbc5.so   
Setup = /usr/lib64/odbc/libodbcmyS.so   //驱动地址
UsageCount = 1
FileUsage = 1
Threading = 0

libmyodbc5.so//驱动地址 64–lib64 32–lib 这个驱动文件是mysql安装后生成的

  • odbc.ini
[freeswitch]
Driver = MySql
SERVER =locahost
PORT =3306
DATABASE = freeswitch_db
USER = root
PASSWORD = root

正确编辑完上面两个文件之后,验证

[root@localhost bin]#isql -v freeswitch root root   //进行验证

如果执行isql -v freeswitch root root ,显示下面的信息,表示数据库连接成功

[root@localhost etc]# isql -v freeswitch root root
+---------------------------------------+
| Connected!                            |
|                                       |
| sql-statement                         |
| help [tablename]                      |
| quit                                  |
|                                       |
+---------------------------------------+
SQL> select * from user

7.软电话配置

1572861098728

8.mysql数据库运行远程访问

本实例意在修改宿主机mysql数据库运行虚拟机进行访问,模拟生产环境freeswitch调用远程数据库获取信息

D:\Users\chenyj91>mysql -uroot -proot
mysql> show databases;
mysql> use mysql;
mysql> select  User,authentication_string,Host from user;
查看到的结果如下:
mysql> select  User,authentication_string,Host from user;
+------+-----------------------+-----------+
| User | authentication_string | Host      |
+------+-----------------------+-----------+
| root |                       | localhost |
+------+-----------------------+-----------+
1 row in set (0.01 sec)

这里可以看出root默认都是localhost访问权限

修改访问权限

mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root';
Query OK, 0 rows affected (0.01 sec)

%代表所有主机,也可以具体到你的主机ip地址,root表示远程连接的密码

刷新权限策略:

mysql> flush privileges;
Query OK, 0 rows affected (0.03 sec)

查看结果:

mysql> select  User,authentication_string,Host from user;
+------+-----------------------+-----------+
| User | authentication_string | Host      |
+------+-----------------------+-----------+
| root |                       | localhost |
| root | NULL                  | %         |
+------+-----------------------+-----------+

修改odbc.ini进行验证

[freeswitch]
Driver = MySql
SERVER =192.168.122.1
PORT =3306
DATABASE = freeswitch_db
USER = root
PASSWORD = root

重启宿主机mysql服务

新建数据表 freeswitch_db

验证:

[root@localhost etc]# isql -v freeswitch root root
+---------------------------------------+
| Connected!                            |
|                                       |
| sql-statement                         |
| help [tablename]                      |
| quit                                  |
|                                       |
+---------------------------------------+

至此 ,连接远程mysql 数据库成功

七、FreeSWITCH使用mysql存储用户

1.创建usr表

该表用于存储拨号计划中的电话号码

CREATE TABLE
    USER
    (
        ID INT(40) NOT NULL AUTO_INCREMENT,
        NAME VARCHAR(40),
        PASSWORD VARCHAR(40),
        PRIMARY KEY (ID)
    )
    ENGINE=InnoDB DEFAULT CHARSET=utf8;

插入数据

#插入两个用户
insert into user (user,password) values('8003','123456')

2.将用户验证转接到lua脚本

将freeswitch/conf/autoload_configs/lua.conf.xml中的两行代码修改为如下所示

<param name="xml-handler-script" value="gen_dir_user_xml.lua" />
<param name="xml-handler-bindings" value="directory" />

3.lua脚本接管用户注册验证

这里调用的脚本是freeswitch/script/gen_dir_user_xml.lua内容如下,默认无该脚本,需自行创建,这里我添加了一些中文日志,等会我们修改完之后再freesitch控制台查看这些日志,验证我们添加的模块是否起作用。

freeswitch.consoleLog("NOTICE","脚本获取user数据...\n");

local req_domain = params:getHeader("domain")
local req_key    = params:getHeader("key")
local req_user   = params:getHeader("user")
local req_password   = params:getHeader("pass")

freeswitch.consoleLog("NOTICE","开始连接Mysql数据库...\r\n");

local dbh = freeswitch.Dbh("freeswitch","root","root");
assert(dbh:connected());
dbh:query("select password from user where name="..req_user,function(row)
        freeswitch.consoleLog("NOTICE","Mysql select password="..string.format("%s\n",row.password))
        req_password=string.format("%s",row.password)
end);
dbh:release();

freeswitch.consoleLog("NOTICE","info:"..req_domain.."--"..req_key.."--"..req_user.."--"..req_password.."\n");

if req_domain ~= nil and req_key ~= nil and req_user ~= nil then
    XML_STRING =
    [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <document type="freeswitch/xml">
      <section name="directory">
        <domain name="]]..req_domain..[[">
          <params>
        <param name="dial-string"
        value="{presence_id=${dialed_user}@${dialed_domain}}${sofia_contact(${dialed_user}@${dialed_domain})}"/>
          </params>
          <groups>
        <group name="default">
          <users>
            <user id="]]..req_user..[[">
              <params>
            <param name="password" value="]]..req_password..[["/>
            <param name="vm-password" value="]]..req_password..[["/>
              </params>
              <variables>
            <variable name="toll_allow" value="domestic,international,local"/>
            <variable name="accountcode" value="]]..req_user..[["/>
            <variable name="user_context" value="default"/>
            <variable name="directory-visible" value="true"/>
            <variable name="directory-exten-visible" value="true"/>
            <variable name="limit_max" value="15"/>
            <variable name="effective_caller_id_name" value="Extension ]]..req_user..[["/>
            <variable name="effective_caller_id_number" value="]]..req_user..[["/>
            <variable name="outbound_caller_id_name" value="${outbound_caller_name}"/>
            <variable name="outbound_caller_id_number" value="${outbound_caller_id}"/>
            <variable name="callgroup" value="techsupport"/>
              </variables>
            </user>
          </users>
        </group>
          </groups>
        </domain>
      </section>
    </document>]]
else
    XML_STRING =
    [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <document type="freeswitch/xml">
      <section name="directory">
      </section>
    </document>]]
end

freeswitch.consoleLog("NOTICE", "debug from gen_dir_user_xml.lua, generated XML:\n" .. XML_STRING .. "\n");

注意:

local dbh = freeswitch.Dbh(“freeswitch”,“root”,“root”);

这个地方的数据库职的是odb.ini文件中[]中的那个名字,不是mysql数据库中的数据库名字

4.注销xml用户验证

修改freeswitch/conf/directory/default.xml中的一部分内容,使得通过xml验证用户的功能失效,这样lua才能真正接管用户注册,删除的内容如下:

<group name="default">
    <users>
      <X-PRE-PROCESS cmd="include" data="default/*.xml"/>
    </users>
 </group>

5.测试

刚才我们在数据库添加了一条8003的账户,密码为123456;本实例这里我们一直尚未修改freeswitch默认密码:1234;只是将密码123456作为一个反例来验证电话号注册的过程。

  • 用软电话按照如下创建一个账户 密码为123456
1572939249705
  • 点击register,在freeswitch控制台看到如下信息
freeswitch@localhost.localdomain> 2019-11-05 07:37:04.090718 [NOTICE] switch_cpp.cpp:1356 脚本获取user数据...
2019-11-05 07:37:04.090718 [NOTICE] switch_cpp.cpp:1356 开始连接Mysql数据库...
2019-11-05 07:37:04.090718 [CRIT] switch_core_sqldb.c:483 Failure! ODBC NOT AVAILABLE! Can't connect to DSN freeswitch_db
2019-11-05 07:37:04.090718 [ERR] freeswitch_lua.cpp:367 Connection failed.  DBH NOT Connected.
2019-11-05 07:37:04.090718 [ERR] mod_lua.cpp:203 /usr/local/freeswitch/scripts/gen_dir_user_xml.lua:11: assertion failed!
stack traceback:
	[C]: in function 'assert'
	/usr/local/freeswitch/scripts/gen_dir_user_xml.lua:11: in main chunk
2019-11-05 07:37:04.090718 [ERR] mod_lua.cpp:270 LUA script parse/execute error!
2019-11-05 07:37:04.090718 [WARNING] sofia_reg.c:2874 Can't find user [8003@192.168.122.132] from 192.168.122.1
You must define a domain called '192.168.122.132' in your directory and add a user with the id="8003" attribute
and you must configure your device to use the proper domain in it's authentication credentials.
2019-11-05 07:37:04.090718 [NOTICE] switch_cpp.cpp:1356 脚本获取user数据...
2019-11-05 07:37:04.090718 [NOTICE] switch_cpp.cpp:1356 开始连接Mysql数据库...
2019-11-05 07:37:04.090718 [CRIT] switch_core_sqldb.c:483 Failure! ODBC NOT AVAILABLE! Can't connect to DSN freeswitch_db
2019-11-05 07:37:04.090718 [ERR] freeswitch_lua.cpp:367 Connection failed.  DBH NOT Connected.
2019-11-05 07:37:04.090718 [ERR] mod_lua.cpp:203 /usr/local/freeswitch/scripts/gen_dir_user_xml.lua:11: assertion failed!
stack traceback:
	[C]: in function 'assert'
	/usr/local/freeswitch/scripts/gen_dir_user_xml.lua:11: in main chunk
2019-11-05 07:37:04.090718 [ERR] mod_lua.cpp:270 LUA script parse/execute error!
2019-11-05 07:37:04.090718 [WARNING] sofia_reg.c:2874 Can't find user [8003@192.168.122.132] from 192.168.122.1
You must define a domain called '192.168.122.132' in your directory and add a user with the id="8003" attribute
and you must configure your device to use the proper domain in it's authentication credentials.
2019-11-05 07:37:07.951807 [NOTICE] switch_cpp.cpp:1356 脚本获取user数据...
2019-11-05 07:37:07.951807 [NOTICE] switch_cpp.cpp:1356 开始连接Mysql数据库...
2019-11-05 07:37:07.951807 [CRIT] switch_core_sqldb.c:483 Failure! ODBC NOT AVAILABLE! Can't connect to DSN freeswitch_db
2019-11-05 07:37:07.951807 [ERR] freeswitch_lua.cpp:367 Connection failed.  DBH NOT Connected.
2019-11-05 07:37:07.951807 [ERR] mod_lua.cpp:203 /usr/local/freeswitch/scripts/gen_dir_user_xml.lua:11: assertion failed!
stack traceback:
	[C]: in function 'assert'
	/usr/local/freeswitch/scripts/gen_dir_user_xml.lua:11: in main chunk
2019-11-05 07:37:07.951807 [ERR] mod_lua.cpp:270 LUA script parse/execute error!
2019-11-05 07:37:07.951807 [WARNING] sofia_reg.c:2874 Can't find user [8003@192.168.122.132] from 192.168.122.1
You must define a domain called '192.168.122.132' in your directory and add a user with the id="8003" attribute
and you must configure your device to use the proper domain in it's authentication credentials.
2019-11-05 07:37:08.050764 [NOTICE] switch_cpp.cpp:1356 脚本获取user数据...
2019-11-05 07:37:08.050764 [NOTICE] switch_cpp.cpp:1356 开始连接Mysql数据库...
2019-11-05 07:37:08.050764 [CRIT] switch_core_sqldb.c:483 Failure! ODBC NOT AVAILABLE! Can't connect to DSN freeswitch_db
2019-11-05 07:37:08.050764 [ERR] freeswitch_lua.cpp:367 Connection failed.  DBH NOT Connected.
2019-11-05 07:37:08.050764 [ERR] mod_lua.cpp:203 /usr/local/freeswitch/scripts/gen_dir_user_xml.lua:11: assertion failed!
stack traceback:
	[C]: in function 'assert'
	/usr/local/freeswitch/scripts/gen_dir_user_xml.lua:11: in main chunk
2019-11-05 07:37:08.050764 [ERR] mod_lua.cpp:270 LUA script parse/execute error!
2019-11-05 07:37:08.050764 [NOTICE] switch_cpp.cpp:1356 脚本获取user数据...
2019-11-05 07:37:08.050764 [NOTICE] switch_cpp.cpp:1356 开始连接Mysql数据库...
2019-11-05 07:37:08.050764 [CRIT] switch_core_sqldb.c:483 Failure! ODBC NOT AVAILABLE! Can't connect to DSN freeswitch_db
2019-11-05 07:37:08.050764 [ERR] freeswitch_lua.cpp:367 Connection failed.  DBH NOT Connected.
2019-11-05 07:37:08.050764 [ERR] mod_lua.cpp:203 /usr/local/freeswitch/scripts/gen_dir_user_xml.lua:11: assertion failed!
stack traceback:
	[C]: in function 'assert'
	/usr/local/freeswitch/scripts/gen_dir_user_xml.lua:11: in main chunk
2019-11-05 07:37:08.050764 [ERR] mod_lua.cpp:270 LUA script parse/execute error!

报错

  • [CRIT] switch_core_sqldb.c:483 Failure! ODBC NOT AVAILABLE!

ODBC驱动不可用

解决办法:
1.首先检查unixODBC与unixODBC-devel安装是否有问题,在看下isql -v DSN是否能连接上
2.如果安装都没问题,那就可能是安装时没有./configure --enable-core-odbc-support,
再进入freeswitch源码目录下,执行重新make && make install就OK了
  • [ERR] switch_odbc.c:368 STATE: IM002 CODE 0 ERROR: [unixODBC][Driver Manager]Data source name not found, and no default driver specified

这里我们看到了刚才添加的日志信息,还有8003

刚才注册电话号码的时候 密码用的是123456,将数据库表user中8003的密码改成1234,且修改软电话注册页面的密码为1234重新点击register.这里为了看的清楚,最好将之前的freeswitch打印的日志信息清理一下;

日志信息如下

freeswitch@localhost.localdomain> 2019-11-05 07:43:00.492554 [NOTICE] switch_cpp.cpp:1356 脚本获取user数据...
2019-11-05 07:43:00.492554 [NOTICE] switch_cpp.cpp:1356 开始连接Mysql数据库...
2019-11-05 07:43:00.492554 [CRIT] switch_core_sqldb.c:483 Failure! ODBC NOT AVAILABLE! Can't connect to DSN freeswitch_db
2019-11-05 07:43:00.492554 [ERR] freeswitch_lua.cpp:367 Connection failed.  DBH NOT Connected.
2019-11-05 07:43:00.492554 [ERR] mod_lua.cpp:203 /usr/local/freeswitch/scripts/gen_dir_user_xml.lua:11: assertion failed!
stack traceback:
	[C]: in function 'assert'
	/usr/local/freeswitch/scripts/gen_dir_user_xml.lua:11: in main chunk
2019-11-05 07:43:00.492554 [ERR] mod_lua.cpp:270 LUA script parse/execute error!
2019-11-05 07:43:00.492554 [WARNING] sofia_reg.c:2874 Can't find user [8003@192.168.122.132] from 192.168.122.1
You must define a domain called '192.168.122.132' in your directory and add a user with the id="8003" attribute
and you must configure your device to use the proper domain in it's authentication credentials.
2019-11-05 07:43:00.591532 [NOTICE] switch_cpp.cpp:1356 脚本获取user数据...
2019-11-05 07:43:00.591532 [NOTICE] switch_cpp.cpp:1356 开始连接Mysql数据库...

这里一个8003的账户就注册成功了

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeSwitch数据库 的相关文章

  • 如何在Lua中创建目录?

    是否可以在 lua 中创建目录 如果是这样 怎么办 有一个 系统 调用 或类似的东西 这是来自内存的 您应该能够使用它来运行任意程序 其中可能包括 mkdir 命令 EDIT 我找到了我的Lua 编程书 在第 203 页 它提到了如何使用
  • 编译 Lua - 创建 .so 文件?

    我正在 Centos 6 5 上编译 Lua 5 2 3 编译 安装工作正常 但是 我还需要编译另一个程序的开发库 我通常会通过这样做来安装它们 yum install lua devel 问题是安装 Lua 5 1 共享库 而不是 5 2
  • 定义函数参数的默认值

    在 Lua wiki 中我找到了一种为缺失参数定义默认值的方法 function myfunction a b c b b or 7 c c or 5 print a b c end 这是唯一的方法吗 PHP 风格myfunction a
  • 在Lua中,处理包含nil的可变参数的正确方法是什么?

    我正在尝试创建一个调试打印函数 它将文件句柄作为第一个参数 首先 我写一个这样的函数 function fprint f for i v in ipairs do f write tostring v f write t end f wri
  • 如何在表格内打印表格的内容? [路亚]

    我想做的只是在表中打印表的内容 例如 local stats table1 tTable1 data 1 tTable2 data2 2 tTable3 data3 3 我并不真正关心表 1 或所有表 而是关心数据变量中的信息 我怎样才能打
  • Lua 中的“加载”有什么作用?

    我试图解决我的理解问题loadLua 脚本中的函数 但没有该命令的任何示例或指南 它在他自己的 Lua 网站上讲述https www lua org manual 5 2 manual html pdf load https www lua
  • 无法在cmake中使用find_package找到Lua标头

    我正在尝试使用 CMake 为我使用 Lua 的项目构建生成 make 文件 当我运行 make 时出现此错误 path to my project luaudio luaudio c 1 17 fatal error lua h No s
  • 代码说“尝试比较数字<=实例”

    It says Players ninjafox56 PlayerGui Shop ShopGui LightSide ChooseSideL 5 尝试比较数字 Rank game Players LocalPlayer leadersta
  • 错误 main.lua:23:尝试索引 upvalue 'Menu' (布尔值)

    我正在尝试用 lua 和 love2d 制作一个主菜单 这是我第一次这样做 遗憾的是没有关于此事的教程 所以我自己尝试了一下 我一直遇到这个错误 我不知道如何解决它 请帮助 完整错误消息 错误main lua 23 尝试索引upvalue
  • 如何使用Lua脚本语言打开Web套接字?

    作为初学者 我想在基于 Linux 的服务器上使用 Lua 打开一个 Web 套接字 该服务器应允许 Android 客户端连接到它 你能给我一些用Lua打开网络套接字的示例代码吗 您两周前已经问过同样的问题并得到了回答 LUA 脚本 We
  • 在 lua 中使用相等运算符比较数字有多安全?

    在我的引擎中 我有一个用于脚本编写的 Lua VM 在脚本中 我写了这样的内容 stage stage 1 if stage 5 then end and objnum tonumber 5 if stage objnum 根据 Lua 来
  • 创建独立的 Lua 可执行文件

    有没有一种简单的方法可以从 Lua 脚本创建独立的 exe 文件 基本上这将涉及链接 Lua 解释器和脚本 我相信这是可能的 PLT 方案允许以相同的方式创建独立的可执行文件 但是到底是如何实现的呢 查看srlua http www tec
  • 十六进制常数 = 格式错误的数字?

    我有一个 Lua 脚本 我试图在其中使用十六进制数字 0x 如果我使用官方 Windows 二进制文件在控制台中运行此脚本 它可以正常工作 但是如果我在我的应用程序中运行它 简单的 dofile 我得到 malformed number n
  • Lua:冒号符号、“自我”和函数定义与调用

    我对定义 调用 Lua 函数时使用的冒号表示法感到非常困惑 我以为我已经明白了 直到我看到这段代码 function string PatternSafe str return str gsub pattern escape replace
  • Lua中如何获取目录列表

    我需要 LUA 中的目录列表 假设我的目录路径为 C Program Files 我需要该特定路径中所有文件夹的列表以及如何搜索该列表中的任何特定文件夹 Example 需要路径 C Program Files 中所有文件夹的列表 以下是上
  • 循环直到在表中找到 2 个特定值?

    我试图找到一种更聪明的方法来解决这个问题 这是与游戏相关的代码的摘录 它循环遍历每个背包的每个插槽 直到找到铲子和绳子 local continue local foundShovel foundRope for i 0 Container
  • 检查lua中是否存在目录?

    如何检查 lua 中是否存在目录 如果可能的话最好不使用 LuaFileSystem 模块 尝试做类似以下 python 行的事情 os path isdir path 这是一种在 Unix 和 Windows 上都适用的方式 无需任何外部
  • Redis 排序集和解决关系

    我正在使用 Redis 排序集来存储我正在处理的项目的排名 我们没有预料到 我们想要如何处理关系 Redis 按字典顺序对具有相同分数的条目进行排序 但我们想要做的是对具有相同分数的所有条目给予相同的排名 例如在以下情况 redis 127
  • lua_resume 的 from 参数的含义

    From Lua 5 2 参考手册 http www lua org manual 5 2 manual html lua resume int lua resume lua State L lua State from int nargs
  • Lua :: 如何编写加载多个CPU的简单程序?

    我还无法用 Lua 编写一个可以加载多个 CPU 的程序 自从Lua通过协程支持这个概念 http www lua org pil 9 4 html 我相信这是可以实现的 我失败的原因可能是以下之一 这在Lua中是不可能的 我写不出来 an

随机推荐

  • 关于\n,\\\n,\\\\\n在java中的split()正则中的理解

    关于 n n n在java中的split 正则中的理解 在做一个题的时候 要把一串字符串dir n tsubdir1 n tsubdir2 n t tfile ext按 n分割 粘贴到idea idea识别自动转义成 也是一个坑 dir n
  • C/C++中调用SQLITE3

    C C 中调用SQLITE3 2011 08 04 17 31 09 分类 LINUX C C 中调用SQLITE3的基本步骤 Sqlite 是一个面向嵌入式系统的数据库 编译完成只有200K 同时支持2T的数据记录 对于嵌入式设备是一个很
  • 操作系统与Linux篇之卷首语

    2023年7月23日 周日晚上 通过纯粹地看操作系统相关书籍来学习操作系统实在是太枯燥和抽象了 我看不到实现的细节 我看不到实际的操作系统代码 这让我学得很难受 所以我决定结合开源的Linux来学习操作系统 我发现这样做不仅学起来更加有趣
  • Expecting property name enclosed in double quotes解决篇

    作者 关注了 Github Github 掘金 进去看看 爱好 Americano More Ice QQ学习交流群 new 811792998 问题 json decoder JSONDecodeError Expecting prope
  • spring boot: 输出json

    spring boot 输出json 注意 关闭java的Terminate后 在重新启动 否则报错 app java启动配置 package com muyang boot1 import org springframework boot
  • curl 命令的学习笔记

    curl 命令的学习笔记 curl 官网 https curl haxx se curl 全称 CommmandLine URL 或 CommandLine Uniform Resource Locator 是用于从服务器传输传输数据或向服
  • 【ARM】Linux内核驱动之定时器

    作者主页 凉开水白菜 作者简介 共同学习 互相监督 热于分享 多加讨论 一起进步 专栏资料 https gitee com stylle linux code 点赞 收藏 再看 养成习惯 订阅的粉丝可通过PC端文末加我微信 可对文章的内容进
  • set -e -x 等等的作用

    set指令能设置所使用shell的执行方式 可依照不同的需求来做设置 a 标示已修改的变量 以供输出至环境变量 b 使被中止的后台程序立刻回报执行状态 C 转向所产生的文件无法覆盖已存在的文件 d Shell预设会用杂凑表记忆使用过的指令
  • VUE 输入框实现光标插入,设置光标位置并删除光标内容

    最近做项目遇到这样一个需求 可以往输入框指定光标出插入内容 并且当删除插入的内容时会先将插入的内容进行光标选中给用户进行提示 当再次删除时才删除内容 而这个需求的核心就在 setSelectionRange 设置光标位置 这个dom api
  • Docker之Nacos的持久化和集群部署

    注1 小插曲 由于虚拟机分配的内存为1G 开到第四个容器时 由于内存不够导致容器启动失败 重新设置4G内存后启动成功 ok 正式进入主题 一 Docker mysql 5 7的持久化存储及远程连接 1 拉取相关镜像 目前网络模式为 brid
  • Flutter中 解决自定义阿里妈妈图标一直显示不出来的问题

    前些天发现了一个蛮有意思的人工智能学习网站 8个字形容一下 通俗易懂 风趣幽默 感觉非常有意思 忍不住分享一下给大家 点击跳转到教程 前言 Flutter中 自定义图标一直显示出来的问题 这里引用的是阿里妈妈图标 问题解决 位置一定要对应好
  • 解决小程序报错getLocation:fail the api need to be declared in the requiredPrivateInfos field in app.json

    报错 1 uniapp项目 在manifest json中打开源码视图 小程序特有相关 mp weixin appid 你的开发者id setting urlCheck true es6 true postcss true minified
  • 【Scala入门】scala基础语法:类和对象,变量和常量

    上一篇请移步 Scala入门 Scala下载及安装 Windows 以及Idea创建第一个scala项目 水w的博客 CSDN博客 目录 一 Scala 二 Scala基础语法 2 1 注释与标识符规范 2 2 变量与常量 案例 变量声明和
  • 摩尔定律到摩尔第二定律

    摩尔定律相信大家都不陌生 由英特尔创始人之一戈登 摩尔提出来的 其内容为 当价格不变时 集成电路上可容纳的元器件的数目 约每隔两年便会增加一倍 而普遍的说法是约每隔18个月便会增加一倍 各种说法总结起来就是 1 集成电路芯片上所集成的电路的
  • 【docker】/var/lib/docker/overlay2/ 占用磁盘问题 最终解决方案

    找IT 挂载了新磁盘 比如 data2 100G 在docker配置文件中 加上这个 systemctl daemon reload 重启docker服务即可 会导致此服务器上的所有docker 容器丢失 需要重新部署 还会导致一个问题 d
  • Hibernate参数校验报错:No validator'javax.validation.constraints.Size' validating type 'java.lang.Integer'.

    javax validation UnexpectedTypeException HV000030 No validator could be found for constraint javax validation constraint
  • Python网络爬虫学习笔记(三)正则表达式

    正则表达式 正则表达式是处理字符串的强大工具 它有自己特定的语法结构 有了它 实现字符串的检索 替换 匹配验证 1 实例引入 正则表达式匹配 也就是用一定的规则将特定的文本提取出来 开源中国提供了正则表达式测试工具 https tool o
  • 虚拟机升级glibc(libc), 导致段错误等问题

    由于确实glibc高版本 需要升级glibc 导致出现段错误等信息 只剩下pwd cd等命令可以执行 这个时候需要靠补全命令查询到原系统使用的libc 2 xx文件 然后使用sln 原系统的重新索引libc so 6文件 sln lib64
  • SOA是什么?

    写这样的blog很容易被人砸砖头 而且我现在在专心做BPEL的研究 http hongsoft iteye com admin blogs 287353 也没有必要现在趟这个混水 不过想想 还是有话要说 定义 SOA是一种做架构的范式 这个
  • FreeSwitch数据库

    Freeswitch数据库 一 ODBC DSN 1 概念 ODBC 开放数据库连接 Open Database Connectivity ODBC https baike baidu com item ODBC 是为解决异构数据库间的数据