Janus WebRTC Server 安装

anus is an open source, general purpose, WebRTC server designed and developed by Meetecho. This version of the server is tailored for Linux systems, although it can be compiled for, and installed on, MacOS machines as well. Windows is not supported, but if that’s a requirement, Janus is known to work in the “Windows Subsystem for Linux” on Windows 10.

For some online demos and documentations, make sure you pay the project website a visit!

To discuss Janus with us and other users, there’s a Google Group called meetecho-janus that you can use. If you encounter bugs, though, please submit an issue on github instead.

Dependencies

To install it, you’ll need to satisfy the following dependencies:

  • Jansson
  • libconfig
  • libnice (at least v0.1.13 suggested, master recommended)
  • OpenSSL (at least v1.0.1e)
  • libsrtp (at least v1.5 suggested)
  • usrsctp (only needed if you are interested in Data Channels)
  • libmicrohttpd (only needed if you are interested in REST support for the Janus API)
  • libwebsockets (only needed if you are interested in WebSockets support for the Janus API)
  • cmake (only needed if you are interested in WebSockets and/or BoringSSL support, as they make use of it)
  • rabbitmq-c (only needed if you are interested in RabbitMQ support for the Janus API or events)
  • paho.mqtt.c (only needed if you are interested in MQTT support for the Janus API or events)
  • nanomsg (only needed if you are interested in Nanomsg support for the Janus API)
  • libcurl (only needed if you are interested in the TURN REST API support)

A couple of plugins depend on a few more libraries:

  • Sofia-SIP (only needed for the SIP plugin)
  • libopus (only needed for the bridge plugin)
  • libogg (needed for the voicemail plugin and/or post-processor)
  • libcurl (only needed if you are interested in RTSP support in the Streaming plugin or in the sample Event Handler plugin)
  • Lua (only needed for the Lua plugin)

Additionally, you’ll need the following libraries and tools:

All of those libraries are usually available on most of the most common distributions. Installing these libraries on a recent Fedora, for instance, is very simple:

yum install libmicrohttpd-devel jansson-devel \
   openssl-devel libsrtp-devel sofia-sip-devel glib2-devel \
   opus-devel libogg-devel libcurl-devel pkgconfig gengetopt \
   libconfig-devel libtool autoconf automake 

Notice that you may have to yum install epel-release as well if you’re attempting an installation on a CentOS machine instead.

On Ubuntu or Debian, it would require something like this:

aptitude install libmicrohttpd-dev libjansson-dev \
	libssl-dev libsrtp-dev libsofia-sip-ua-dev libglib2.0-dev \
	libopus-dev libogg-dev libcurl4-openssl-dev liblua5.3-dev \
	libconfig-dev pkg-config gengetopt libtool automake 
  • Note: please notice that libopus may not be available out of the box on Ubuntu or Debian, unless you’re using a recent version (e.g., Ubuntu 14.04 LTS). In that case, you’ll have to install it manually.

While libnice is typically available in most distros as a package, the version available out of the box in Ubuntu is known to cause problems. As such, we always recommend manually compiling and installing the master version of libnice. Installation of libnice master is quite straightforward:

git clone https://gitlab.freedesktop.org/libnice/libnice
cd libnice
./autogen.sh
./configure --prefix=/usr
make && sudo make install 
  • Note: Make sure you remove the distro version first, or you’ll cause conflicts between the installations. In case you want to keep both for some reason, for custom installations of libnice you can also run pkg-config --cflags --libs nice to make sure Janus can find the right installation. If that fails, you may need to set the PKG_CONFIG_PATH environment variable prior to compiling Janus, e.g., export PKG_CONFIG_PATH=/path/to/libnice/lib/pkgconfig

In case you’re interested in compiling the sample Event Handler plugin, you’ll need to install the development version of libcurl as well (usually libcurl-devel on Fedora/CentOS, libcurl4-openssl-dev on Ubuntu/Debian).

If your distro ships a pre-1.5 version of libsrtp, you’ll have to uninstall that version and install 1.5.x, 1.6.x or 2.x manually. In fact, 1.4.x is known to cause several issues with WebRTC. Installation of version 1.5.4 is quite straightforward:

wget https://github.com/cisco/libsrtp/archive/v1.5.4.tar.gz
tar xfv v1.5.4.tar.gz
cd libsrtp-1.5.4
./configure --prefix=/usr --enable-openssl
make shared_library && sudo make install 

The instructions for version 2.x are practically the same. Notice that the following steps are for version 2.2.0, but there may be more recent versions available:

wget https://github.com/cisco/libsrtp/archive/v2.2.0.tar.gz
tar xfv v2.2.0.tar.gz
cd libsrtp-2.2.0
./configure --prefix=/usr --enable-openssl
make shared_library && sudo make install 

The Janus configure script autodetects which one you have installed and links to the correct library automatically, choosing 2.x if both are installed. If you want 1.5 or 1.6 to be picked, pass --disable-libsrtp2 when configuring Janus to force it to use the older version instead.

  • Note: when installing libsrtp, no matter which version, you may need to pass --libdir=/usr/lib64 to the configure script if you’re installing on a x86_64 distribution.

If you want to make use of BoringSSL instead of OpenSSL (e.g., because you want to take advantage of --enable-dtls-settimeout), you’ll have to manually install it to a specific location. Use the following steps:

git clone https://boringssl.googlesource.com/boringssl
cd boringssl
# Don't barf on errors
sed -i s/" -Werror"//g CMakeLists.txt
# Build
mkdir -p build
cd build
cmake -DCMAKE_CXX_FLAGS="-lrt" ..
make
cd ..
# Install
sudo mkdir -p /opt/boringssl
sudo cp -R include /opt/boringssl/
sudo mkdir -p /opt/boringssl/lib
sudo cp build/ssl/libssl.a /opt/boringssl/lib/
sudo cp build/crypto/libcrypto.a /opt/boringssl/lib/ 

Once the library is installed, you’ll have to pass an additional --enable-boringssl flag to the configure script, as by default Janus will be built assuming OpenSSL will be used. By default, Janus expects BoringSSL to be installed in /opt/boringssl — if it’s installed in another location, pass the path to the configure script as such: --enable-boringssl=/path/to/boringssl If you were using OpenSSL and want to switch to BoringSSL, make sure you also do a make clean in the Janus folder before compiling with the new BoringSSL support. If you enabled BoringSSL support and also want Janus to detect and react to DTLS timeouts with faster retransmissions, then pass --enable-dtls-settimeout to the configure script too.

For what concerns usrsctp, which is needed for Data Channels support, it is usually not available in repositories, so if you’re interested in them (support is optional) you’ll have to install it manually. It is a pretty easy and standard process:

git clone https://github.com/sctplab/usrsctp
cd usrsctp
./bootstrap
./configure --prefix=/usr && make && sudo make install 
  • Note: you may need to pass --libdir=/usr/lib64 to the configure script if you’re installing on a x86_64 distribution.

The same applies for libwebsockets, which is needed for the optional WebSockets support. If you’re interested in supporting WebSockets to control Janus, as an alternative (or replacement) to the default plain HTTP REST API, you’ll have to install it manually:

git clone https://libwebsockets.org/repo/libwebsockets
cd libwebsockets
# If you want the stable version of libwebsockets, uncomment the next line
# git checkout v2.4-stable
mkdir build
cd build
# See https://github.com/meetecho/janus-gateway/issues/732 re: LWS_MAX_SMP
cmake -DLWS_MAX_SMP=1 -DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_C_FLAGS="-fpic" ..
make && sudo make install 

The same applies for Eclipse Paho MQTT C client library, which is needed for the optional MQTT support. If you’re interested in integrating MQTT channels as an alternative (or replacement) to HTTP and/or WebSockets to control Janus, or as a carrier of Janus Events, you can install the latest version with the following steps:

git clone https://github.com/eclipse/paho.mqtt.c.git
cd paho.mqtt.c
make && sudo make install 
  • Note: you may want to set up a different install path for the library, to achieve that, replace the last command by ‘sudo prefix=/usr make install’.

In case you’re interested in Nanomsg support, you’ll need to install the related C library. It is usually available as an easily installable package in pretty much all repositories. The following is an example on how to install it on Ubuntu:

aptitude install libnanomsg-dev 

Finally, the same can be said for rabbitmq-c as well, which is needed for the optional RabbitMQ support. In fact, several different versions of the library can be found, and the versions usually available in most distribution repositories are not up-do-date with respect to the current state of the development. As such, if you’re interested in integrating RabbitMQ queues as an alternative (or replacement) to HTTP and/or WebSockets to control Janus, you can install the latest version with the following steps:

git clone https://github.com/alanxz/rabbitmq-c
cd rabbitmq-c
git submodule init
git submodule update
mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
make && sudo make install 
  • Note: you may need to pass --libdir=/usr/lib64 to the configure script if you’re installing on a x86_64 distribution.

To conclude, should you be interested in building the Janus documentation as well, you’ll need some additional tools too:

On Fedora:

yum install doxygen graphviz 

On Ubuntu/Debian:

aptitude install doxygen graphviz 

Compile

Once you have installed all the dependencies, get the code:

git clone https://github.com/meetecho/janus-gateway.git
cd janus-gateway 

Then just use:

sh autogen.sh 

to generate the configure file. After that, configure and compile as usual to start the whole compilation process:

./configure --prefix=/opt/janus
make
make install 

Since Janus requires configuration files for both the core and its modules in order to work, you’ll probably also want to install the default configuration files to use, which you can do this way:

make configs 

Remember to only do this once, or otherwise a subsequent make configs will overwrite any configuration file you may have modified in themeanwhile.

If you’ve installed the above libraries but are not interested, for instance, in Data Channels, WebSockets, MQTT and/or RabbitMQ, you can disable them when configuring:

./configure --disable-websockets --disable-data-channels --disable-rabbitmq --disable-mqtt 

There are configuration flags for pretty much all external modules and many of the features, so you may want to issue a ./configure --help to dig through the available options. A summary of what’s going to be built will always appear after you do a configure, allowing you to double check if what you need and don’t need is there.

If Doxygen and graphviz are available, the process can also build the documentation for you. By default the compilation process will not try to build the documentation, so if you instead prefer to build it, use the --enable-docs configuration option:

./configure --enable-docs 

You can also selectively enable/disable other features (e.g., specific plugins you don’t care about, or whether or not you want to build the recordings post-processor). Use the –help option when configuring for more info.

Building on MacOS

While most of the above instructions will work when compiling Janus on MacOS as well, there are a few aspects to highlight when doing that.

First of all, you can use brew to install most of the dependencies:

brew install jansson libnice openssl srtp libusrsctp libmicrohttpd \
	libwebsockets cmake rabbitmq-c sofia-sip opus libogg curl glib \
	libconfig pkg-config gengetopt autoconf automake libtool 

For what concerns libwebsockets, though, make sure that the installed version is higher than 2.4.1, or you might encounter the problems described in this post. If brew doesn’t provide a more recent version, you’ll have to install the library manually.

Notice that you may need to provide a custom prefix and PKG_CONFIG_PATH when configuring Janus as well, e.g.:

./configure --prefix=/usr/local/janus PKG_CONFIG_PATH=/usr/local/opt/openssl/lib/pkgconfig 

Everything else works exactly the same way as on Linux.

Configure and start

To start the server, you can use the janus executable. There are several things you can configure, either in a configuration file:

<installdir>/etc/janus/janus.jcfg 

or on the command line:

<installdir>/bin/janus --help

janus 0.7.5

Usage: janus [OPTIONS]...

-h, --help                    Print help and exit
-V, --version                 Print version and exit
-b, --daemon                  Launch Janus in background as a daemon
                              (default=off)
-p, --pid-file=path           Open the specified PID file when starting Janus
                              (default=none)
-N, --disable-stdout          Disable stdout based logging  (default=off)
-L, --log-file=path           Log to the specified file (default=stdout only)
-H  --cwd-path                Working directory for Janus daemon process
                              (default=/)
-i, --interface=ipaddress     Interface to use (will be the public IP)
-P, --plugins-folder=path     Plugins folder (default=./plugins)
-C, --config=filename         Configuration file to use
-F, --configs-folder=path     Configuration files folder (default=./conf)
-c, --cert-pem=filename       DTLS certificate
-k, --cert-key=filename       DTLS certificate key
-K, --cert-pwd=text           DTLS certificate key passphrase (if needed)
-S, --stun-server=filename    STUN server(:port) to use, if needed (e.g.,
							  Janus behind NAT, default=none)
-1, --nat-1-1=ip              Public IP to put in all host candidates,
                              assuming a 1:1 NAT is in place (e.g., Amazon
                              EC2 instances, default=none)
-E, --ice-enforce-list=list   Comma-separated list of the only interfaces to
                              use for ICE gathering; partial strings are
                              supported (e.g., eth0 or eno1,wlan0,
                              default=none)
-X, --ice-ignore-list=list    Comma-separated list of interfaces or IP
                              addresses to ignore for ICE gathering;
                              partial strings are supported (e.g.,
                              vmnet8,192.168.0.1,10.0.0.1 or
                              vmnet,192.168., default=vmnet)
-6, --ipv6-candidates         Whether to enable IPv6 candidates or not
                              (experimental)  (default=off)
-l, --libnice-debug           Whether to enable libnice debugging or not
                              (default=off)
-f, --full-trickle            Do full-trickle instead of half-trickle
                              (default=off)
-I, --ice-lite                Whether to enable the ICE Lite mode or not
                              (default=off)
-T, --ice-tcp                 Whether to enable ICE-TCP or not (warning: only
                              works with ICE Lite)
                              (default=off)
-R, --rfc-4588                Whether to enable RFC4588 retransmissions
                              support or not  (default=off)
-q, --max-nack-queue=number   Maximum size of the NACK queue (in ms) per user
                              for retransmissions
-t, --no-media-timer=number   Time (in s) that should pass with no media
                              (audio or video) being received before Janus
                              notifies you about this
-W, --slowlink-threshold=number
                              Number of lost packets (per s) that should
                              trigger a 'slowlink' Janus API event to users
-r, --rtp-port-range=min-max  Port range to use for RTP/RTCP (only available
							  if the installed libnice supports it)
-B, --twcc-period=number      How often (in ms) to send TWCC feedback back to
                              senders, if negotiated (default=1s)
-n, --server-name=name        Public name of this Janus instance
                              (default=MyJanusInstance)
-s, --session-timeout=number  Session timeout value, in seconds (default=60)
-m, --reclaim-session-timeout=number
                              Reclaim session timeout value, in seconds
                              (default=0)
-d, --debug-level=1-7         Debug/logging level (0=disable debugging,
                              7=maximum debug level; default=4)
-D, --debug-timestamps        Enable debug/logging timestamps  (default=off)
-o, --disable-colors          Disable color in the logging  (default=off)
-M, --debug-locks             Enable debugging of locks/mutexes (very
                              verbose!)  (default=off)
-a, --apisecret=randomstring  API secret all requests need to pass in order
                              to be accepted by Janus (useful when wrapping
                              Janus API requests in a server, none by
                              default)
-A, --token-auth              Enable token-based authentication for all
                              requests  (default=off)
-e, --event-handlers          Enable event handlers  (default=off) 

Options passed through the command line have the precedence on those specified in the configuration file. To start the server, simply run:

<installdir>/bin/janus 

This will start the server, and have it look at the configuration file.

Make sure you have a look at all of the configuration files, to tailor Janus to your specific needs: each configuration file is documented, so it shouldn’t be hard to make changes according to your requirements. The repo comes with some defaults (assuming you issues make configs after installing the server) that tend to make sense for generic deployments, and also includes some sample configurations for all the plugins (e.g., web servers to listen on, conference rooms to create, streaming mountpoints to make available at startup, etc.).

To test whether it’s working correctly, you can use the demos provided with this package in the html folder: these are exactly the same demos available online on the project website. Just copy the file it contains in a webserver, or use a userspace webserver to serve the files in the html folder (e.g., with php or python), and open the index.html page in either Chrome or Firefox. A list of demo pages exploiting the different plugins will be available. Remember to edit the transport/port details in the demo JavaScript files if you changed any transport-related configuration from its defaults. Besides, the demos refer to the pre-configured plugin resources, so if you add some new resources (e.g., a new videoconference) you may have to tweak the demo pages to actually use them.

WebRTC服务器开源项目汇总

一、重点参考
1.1 知乎
原文链接: http://www.zhihu.com/question/25497090
可以用WebRTC来做视频直播吗?
经常看到WebRTC的点对点的视频, 能不能做一个平台,
让别人通过WebRTC播放视频直播,让粉丝都可以看见? 有什么方案讲讲?

米小嘉:
可以的. webrtc就是浏览器直接有实时视频功能, 不需要额外的插件, 但有可能是浏览器的默认插件
发布于 2014-09-26 9 条评论       
 
刘津玮:
我所在的项目用这个技术两年多了,先说结论:完全可以!

但是,凡事总有但是,也没那么简单。你以为调用几个Chrome的API就能直播了?too simple

楼上 米小嘉 的回答不对,WebRTC用的不是插件,是Chrome自带的功能,是原生js的API,也没有什么浏览器自带的插件。
楼上 煎饼果子社长 的方法也不对,WebRTC的API不仅仅是给你获取本地信源的,
所谓RTC是real time communication的缩写,自然这套API是带传输功能的。
所以获取图像信源之后不应该用websocket发送图像数据,
而是直接用WebRTC的通信相关API发送图像和声音(这套API是同时支持图像和声音的)数据。

所以,正确的方法是什么呢?
1、你得有一个实现了WebRTC相关协议的客户端。比如Chrome浏览器。
2、架设一个类似MCU系统的服务器。(不知道MCU是什么?看这:MCU(视频会议系统中心控制设备))

第一步,用你的客户端,比如Chrome浏览器,通过WebRTC相关的媒体API获取图像及声音信源,
        再用WebRTC中的通信API将图像和声音数据发送到MCU服务器。
第二步,MCU服务器根据你的需求对图像和声音数据进行必要的处理,比如压缩、混音等。
第三步,需要看直播的用户,通过他们的Chrome浏览器,链接上你的MCU服务器,并收取服务器转发来的图像和声音流。

先说步骤一,如果你只是做着玩玩,完全可以直接用Chrome浏览器做你的直播客户端。
把摄像头麦克风连上电脑之后,Chrome可以用相关的js的API获取到摄像头和麦克风的数据。
缺点就是如果长时间直播,Chrome的稳定性堪忧,我不是吓唬你。
我们项目的经验是,chrome这样运行24小时以上内存占用很厉害,而且容易崩溃。

第二步,你可能要问,WebRTC可以直接在浏览器之间P2P地传输流,为什么还要有中转的MCU服务器?
因为Chrome的功能很弱,视频的分辨率控制、多路语音的混音都做不了,所以需要MCU参与。
最重要的是,Chrome同时给6个客户端发视频流就很消耗资源了,
所以你如果有超过10个用户收看的话,Chrome很容易崩溃。

第三步就比较简单了,没什么好说的。
最后最后,还是老话题,兼容性。你可以查一下现在支持的浏览器有款,IE据说支持,
但是我们研究了一下好像他用的协议和Chrome不一样,不能互通。firefox和opera情况也不是很理想。

将空: 
说的有道理,受益非浅
2015-03-31   

Ryan:
mcu类似media Server的角色吧?有点类似red5?
2015-04-04   

刘津玮(作者) 回复 Ryan
对,类似red5,但是MCU这货是我们自己写的,所以没那么强大的功能,基本上是要什么功能的时候就自己写一个加上去
2015-04-05   

知乎用户
说的很详细,个人确实感觉中间需要个服务器~
2015-04-10   

王宇鹏
服务器端有免费或收费的软件吗?
2015-04-12   

刘津玮(作者) 回复 王宇鹏
http://lynckia.com 你可以参考一下这个
2015-04-12   

孙知乎
受教了
2015-04-13   

刘津玮(作者) 回复 孙知乎
受教还不去点赞加感谢?!( ╯#-_-)╯┴—┴
2015-04-13   

孙知乎 回复 刘津玮(作者)
(⊙o⊙)…。。已点
2015-04-13   

周昌:
我弄一个手机视频直播应用,刚刚上线,基于WebRTC技术,Mesh tree的网络架构,
浏览器之间走P2P Relay, 正在产品迭代中。产品见: http://yacamera.com
发布于 2014-10-01 1 条评论       
 
知乎用户:
1对N的直播, 一般都是服务器转发的吧.
发布于 2014-10-12 添加评论       
 
廖郡:
请问两台电脑,只有一台电脑有摄像头,能不能实现视频传输。WebRTC
发布于 2014-10-24 1 条评论       
 
鲁强:
补充一点,直播应该是流媒体处理及利用上早就有的概念。
WebRTC只是提供了一种可以替换现有的直播系统中的流媒体传输及处理的框架。

同时,其它答案也提到了,做直播或者视频内的服务,很多都会牵涉到对流媒体的Mix处理及转发。
在这里我需要提醒大家,Video相关的mix在webrtc的底层框架中是没有的,
这里有很大的坑,不是那么简单就能填起来的,请大家在做产品预言的时候深入考虑下哦:),
Audio相关的Mix倒是在webrtc的底层音频相关的框架中已经有了,很容易就可以被大家拿来使用
(虽然chrome啥的,都是只用来做p2p)。

用WebRTC来实现一个支持直播的服务是完全可行的,
但是,要做到直播的交互性,以及大规模的并发(比如一个主播,数以千计的观众)这是做直播最需要考虑的问题。
WebRTC在这里点上只是提供了一个流媒体的传输途径包括音频、视频编解码的接入等,
这些都是可以借鉴或者使用它来作为实现直播的一个部分。
但是,只用webrtc,你也只能做一个简单的玩具,做产品的话,
请更多考虑产品的应用场景,用户量,带宽需求,服务器搭设及运维。
发布于 2015-04-16 2 条评论       
 
煎饼果子社长:
完全可以,直播我理解是点对多的方式,需要服务器中转分发。

获取信源就用webrtc获取你的桌面或者某应用的图像,可以选择,webrtc的API中可以设置。
然后用WebSocket发送到你的服务器(不是唯一的办法,只是这种方法试过可行),然后转发。
客户端也是一样的原理,websocket接收,直接用html5自带的就能播放信源。

唯一不足,声源需要用类似方法单独处理,因为桌面只有图像,不过原理相似。
发布于 2015-03-30 添加评论  

二、Jitsi视频会议系统
1. 基于WebRTC的多人视频会议
25 July 2014
最近两周在调研和搭建基于WebRTC的多人视频会议系统。目前已经搭建成功,可以在http://jitsi.shengbin.me/试用。
这个系统无需注册和登录,只要多人访问同一个URL(含有系统为每个房间分配的特定ID),就可以进行视频会议。
如果上面那个链接失效,可以尝试国外一个同样的系统:https://meet.jit.si/。
使用视频会议系统需要客户端电脑提供摄像头功能;至于带宽,当然是越大越好了。
下面总结一下该系统的组成。

2. 客户端
客户端是一个Web App的形式,包括HTML、CSS、JavaScript代码组成的网页。HTML和CSS来构造聊天室的界面,JavaScript来实现功能。由于功能比较复杂,JS代码也较多。
通过WebRTC,客户端从用户摄像头获取图像并传给服务器,来实现视频会议。由于WebRTC只在Chrome、Opera、Firefox上支持,而Firefox有相关的bug尚未解决,所以客户端只能运行于Chrome或者Opera浏览器。

3. 服务器
服务器端包含多个部分。下面分别介绍。
Nginx(http://nginx.org/)
Nginx是一个Web服务器,与著名的Apache同类。它的用途是提供网页访问。

Prosody(http://prosody.im/)
Prosody是一个XMPP服务器。XMPP全称是Extensible Messaging and Presence Protocol,即可扩展通信和表示协议。
它是一种即时通信协议,主要是实现文字聊天。
XMPP的前身是Jabber,一个开源的即时通信协议。Jabber被IETF标准化为XMPP。Google Talk用的就是它。

Jitsi-Videobridge(https://jitsi.org/Projects/JitsiVideobridge)
Jitsi-Videobridge用于处理视频传输,也就是视频流在各参与者之间的转发。
如果没有这个组件,各参与者能文字聊天,但无法互相看见。
转发意味着服务器要从N个参与者那里接受视频流,然后给每个参与者发送其他N-1个参与者的视频数据,
这对服务器带宽要求很高。但由于未对视频做任何处理,CPU负载并不高。

Restund(http://www.creytiv.com/restund.html)
这是一个STUN/TURN服务器。STUN是一种NAT穿透技术,用于帮助处在内网的主机确定自己的公网IP和端口,
从而与别的主机建立直接连接(WebRTC中PeerConnection)。
TURN是STUN的增强版,可以在无法穿透NAT进行直连的情况下提供数据的转发。
上述整个系统都是开源的,更多信息可参见相关的GitHub代码库和Jitsi主页。

三、Janus 视频直播系统
前面说过,WebRTC 是用来解决端到端的实时通信问题,也就是说它很适合用在网络电话这种需要双向视频通话的场景上。网上大部分 WebRTC 的 Demo 也都是在页面上放两个 Video,分别来播 localStream 和 RemoteStream。

3.1 无MediaServer的视频直播系统
那么究竟 WebRTC 能否用来实现单向一对多直播呢?当然可以,而且貌似还很简单:
Step1: 首先必须有一个专门负责调用 getUserMedia 采集音视频的页面,我称之为信源服务;
Step2: 打开直播页面时,建立到信源服务的 PeerConnection,并通过 DataChannel 通知信源服务;
Step3: 信源服务收到通知后,通过对应 PeerConnection 的 addStream 方法提供直播流;
Step4: 直播页面监听 PeerConnection 的 onaddstream 事件,将获得的直播流用丢给 Video 播放;

为了方便,我使用了 PeerJS 这个开源项目来验证上面这个过程。
PeerJS 对 WebRTC Api 进行了封装,使用更简单。
它还提供了用来辅助建立连接的 Signaling 服务,在官网注册一个 Api Key 就能用。
也可以通过 PeerJS Server 搭建自己的服务,只需要通过 
npm install peer 装好 peer 后,再通过下面这行命令启动就可以了:
peerjs –port 9000 –key peerjs
启动好 Peer Server,在页面中引入 peer.js 就可以开始玩了。
首先, 实现信源服务:
//由于其它端都要连它,指定一个固定的 ID
var peer = new Peer(‘Server’, {
    host: ‘qgy18.imququ.com’, 
    port: 9003, 
    path: ‘/’,
    config: {
        ‘iceServers’: [
              { url: ‘stun:stun.l.google.com:19302’ }
        ]
    }
});

navigator.getUserMedia({ audio: false, video: true }, function(stream) {
    window.stream = stream;
}, function() { /*…*/ });

peer.on(‘connection’, function(conn) {
    conn.on(‘data’, function(clientId){
        var call = peer.call(clientId, window.stream);

        call.on(‘close’, function() { /*…*/ });
    });
});

然后,就是直播服务:
//随机生成一个 ID
var clientId = (+new Date).toString(36) + ‘_’ + (Math.random().toString()).split(‘.’)[1];

var peer = new Peer(clientId, {
    host: ‘qgy18.imququ.com’, 
    port: 9003, 
    path: ‘/’,
    config: {
        ‘iceServers’: [
              { url: ‘stun:stun.l.google.com:19302’ }
        ]
    }
});

var conn = peer.connect(‘Server’);

conn.on(‘open’, function() {
    conn.send(clientId);
});

peer.on(‘call’, function(call) {
    call.answer();
    call.on(‘stream’, function(remoteStream) {
        var video = document.getElementById(‘video’);
        video.src = window.URL.createObjectURL(remoteStream);
    });

    call.on(‘close’, function() { /*…*/ });
});

直播页面通过指定 ID 的方式跟信源服务建立端到端连接,
然后通过 DataChannel 告诉信源服务自己的 ID,信源服务收到消息后,
主动把直播流发过来,直播页面应答后播放就可以了。整个过程原理就这么简单,
这里有一个「完整的 Demo」。
看完上面的 Demo,你也许会想原来使用 WebRTC 直播这么简单,随便找台带摄像头的电脑,
开个浏览器就能提供直播服务,那还搞 HLS、RTMP 什么的干嘛。

3.2 Janus视频直播系统应用简介
实际上,现实并没有那么美好,这个 Demo 也就玩玩儿还可以,真正使用起来问题还大着呢!
首先,虽然说在 WebRTC 直播方案中,服务端只扮演桥梁的工作,
实际数据传输直接发生在端到端之间,但前面说过仍然会有 8% 的情况完全不能直连。
要保证服务的高可用性,还是得考虑部署 TURN 这种复杂而昂贵的中转服务。
其次,Chrome 对每个 Tab 允许连接的终端数有限制,最多 256 个。
实际上,在我最新的 Retina Macbook Pro 上,差不多有 10 个连接时,
Chrome 就开始变得无比卡,风扇呼呼地转,内存被吃掉 6G,CPU 一直跑满,
网络吞吐开始忙不过来,直播服务也开始变得极其不稳定。

所以实际使用方案中,一般还是需要 Media Server 的支持,
把「端到多端」变成「端到 Media Server 到多端」的架构。
Media Server 可以有更好的性能和带宽,可以自己实现 WebRTC 协议,
也就有了支持更多用户的可能。

我找到一个名为 Janus 的 WebRTC Gateway,这个开源项目用 C 语言实现了对 WebRTC 的支持。
Janus 自身实现得很简单,提供插件机制来支持不同的业务逻辑,
配合官方自带插件就可以用来实现高效的 Media Server 服务。
Janus 官方提供的 Demo 在这里,我也尝试在我的 VPS 上部署了一套。

Janus 有个 Streaming 插件,可以接受 GStreamer 推送的音视频流,
然后通过 PeerConnection 推送给所有的用户。由于 GStreamer 可以直接读摄像头,
也就不用再走 WebRTC 的 MediaStream 获取视频,这样架构就变成了传统的服务器到端了。
整个过程比较复杂和曲折,这里不写了,有兴趣的同学可以单独找我讨论。

3.3 Janus视频直播系统官网
链接:
http://janus.conf.meetecho.com/
https://github.com/meetecho/janus-gateway

Janus: the general purpose WebRTC server

Janus is a WebRTC Server developed by Meetecho conceived to be a general purpose one. As such, it doesn’t provide any functionality per se other than implementing the means to set up a WebRTC media communication with a browser, exchanging JSON messages with it, and relaying RTP/RTCP and messages between browsers and the server-side application logic they’re attached to. Any specific feature/application is provided by server side plugins, that browsers can then contact via Janus to take advantage of the functionality they provide. Example of such plugins can be implementations of applications like echo tests, conference bridges, media recorders, SIP gateways and the like.

The reason for this is simple: we wanted something that would have a small footprint (hence a C implementation) and that we could only equip with what was really needed(hence pluggable modules). That is, something that would allow us to deploy either a full-fledged WebRTC gateway on the cloud, or a small nettop/box to handle a specific use case.

Janus配置文件詳解

General

基本配置,配置和插件的路徑,日誌輸出方式,運行方式等配置.

變量 說明 示例
configs_folder 配置文件目錄路徑 configs_folder=/opt/janus/etc/janus
plugins_folder 插件目錄路徑 plugins_folder=/opt/janus/lib/janus/plugins
transports_folder 傳輸協議目錄路徑,一般是第三方傳輸方面依賴動態庫,默認即可 transports_folder=/opt/janus/lib/janus/transports
events_folder 事件句柄目錄路徑,一般是第三方事件方面依賴的動態庫,默認即可 events_folder=/opt/janus/lib/janus/events
log_to_stdout 日誌是否輸出到標準輸出上,默認爲 true log_to_stdout = false
log_to_file 日誌文件路徑 log_to_file = /path/to/janus.log
daemonize 是否後臺運行, 默認在前臺運行 daemonize = true
pid_file pid 文件路徑, pid 文件在 janus 運行是被創建,關閉時刪除 pid_file = /path/to/janus.pid
interface 使用的接口(在 SDP 中將使用)現在未使用 interface = 1.2.3.4
debug_level 記錄日誌等級, 可用值爲 0-7 debug_level = 4
debug_timestamps 是否每行日誌顯示時間戳 debug_timestamps = yes
debug_colors 日誌中是否禁用顏色 debug_colors = no
debug_locks 是否使能鎖調試(非常詳細) debug_locks = yes
api_secret 所有 janus 請求必須包含的字符串,由 janus core 接受或驗證, 如果假裝所有的請求在你 的服務器這就有用,不想讓其他應用程序混 亂 api_secret = janusrocks
token_auth 基於令牌的身份驗證,該機制強迫用戶在所 有的請求中提供有效的令牌,在想要對來自 web 請求進行身份驗證非常有用 token_auth = yes
token_auth_secret 和 token_auth 一起使用,使用 HMAC-SHA1 簽名令牌, 注意, 沒有該選項, 管理 api 有添加和刪除令牌的操作 token_auth_secret = janus
admin_secret 所有 janus 請求必須包含的由管理或監控接 收或驗證的字符串,只有在所有可用的傳輸 中使能了管理 api 才需要 admin_secret = janusoverlord
server_name 這個 janus 實例的公開名, 將出現在 info 請 求 server_name = MyJanusInstance
session_timeout 會話超時時間,默認 60s session_timeout = 60
reclaim_session_timeout 會話回收時間,默認 0s reclaim_session_timeout = 0
candidates_ti meout 申請超時時間, 注意設置 0 將被因無效數值 而被忽略 candidates_timeout = 45
recordings_tmp_ext 臨時記錄文件名 recordings_tmp_ext = tmp
event_loops 啓動線程數 event_loops = 8

Certificates

DTLS使用的證書和祕鑰(和所需密碼)生成

變量 說明 示例
cert_pem 證書 cert_pem=/opt/janus/share/janus/certs/mycert.pem
cert_key 密鑰 cert_key=/opt/janus/share/janus/certs/mycert.key
cert_pwd 密碼 cert_pwd = secretpassphrase

Media

與媒體相關的配置

變量 說明 示例
ipv6 是否支持 ipv6 ipv6 = true
max_nack_queue 重新傳輸的 NACK 隊列最大值單位毫秒,默認 500 max_nack_queue=500
rfc_4588 是否支持協商 rfc_4588 = yes
rtp_port_range 用於 RTP 和 RTCP 的端口的範圍,默認不考慮範圍 rtp_port_range=20000-40000
dtls_mtu 啓動 DTLS 的 MTU(默認爲 1200,它自動適應) dtls_mtu = 1200
no_media_timer 沒有 media 數據多長時間 janus 通知,單位爲秒默認 1 no_media_timer=1
dtls_timeout 定製重傳的頻率,注意較低的 值(例如 100ms)通常會使連接 速度更快時間,但如果用戶的 RTT 很高,則可能無法工作 合理的權衡(通常是 2*最大期 望 RTT) dtls_timeout = 500

NAT

與NAT相關的內容,如果網關位於NAT之後,可以配置STUN/TURN用於收集候選對象的服務器

變量 說明 示例
stun_server STUN 服務器地址 stun_server = stun.voip.eutelia.it
stun_port STUN 服務器端口 stun_port = 3478
nice_debug NAT debug開關 nice_debug = false
full_trickle 默認 half-trickle full_trickle = false
ice_lite ICE-Lite 模塊, 默認false ice_lite = true
ice_tcp 支持 ICE-Lite ice_tcp = true
nat_1_1_mapping 內外網地址映射 nat_1_1_mapping = 1.2.3.4
turn_server Turn 服務器地址 turn_server = myturnserver.com
turn_port Turn 服務器端口 turn_port = 3478
turn_type Turn 服務器IP類型 turn_type = udp
turn_user 用戶名 turn_user = myuser
turn_pwd 密碼 turn_pwd = mypassword
turn_rest_api TURN REST API 地址 turn_rest_api = http://yourbackend.com/path/to/api
turn_rest_api_key 密鑰 turn_rest_api_key=anyapikeyyoumayhaveset
turn_rest_api_method 方法 turn_rest_api_method = GET
ice_enforce_list 設置並傳遞一個逗號分隔 的接口或 IP 地址列表,網 關選擇 ice_enforce_list = eth0/ ice_enforce_list = eth0,192.168.0.1
ice_ignore_list 忽略的網關 ice_ignore_list = vmnet8,192.168.0.1,10.0.0.1

Plugins

選擇應該使用哪個插件

參數 說明 示例
disable 禁用插件, 用逗號會隔 disable = libjanus_rabbitmq.so

Events

允許您接收來自 Janus happens 的實時事件的事件處理程序

參數 說明 示例
broadcast 所有可用的事件處理程序都是啓用的 broadcast = yes
disable 禁用的事件 disable=libjanus_sampleevh.so
stats_period 每個事件處理的統計傳輸的 時間 stats_period = 5

mysql – 启动错误InnoDB: mmap(137363456 bytes) failed; errno 12

上午mysql出现了问题,很纠结,最后找到了原因,原因是内存不够用;

190925  9:25:01 [Note] Plugin ‘FEDERATED’ is disabled.
190925  9:25:01 InnoDB: The InnoDB memory heap is disabled
190925  9:25:01 InnoDB: Mutexes and rw_locks use GCC atomic builtins
190925  9:25:01 InnoDB: Compressed tables use zlib 1.2.7
190925  9:25:01 InnoDB: Using Linux native AIO
190925  9:25:01 InnoDB: Initializing buffer pool, size = 1.0G
InnoDB: mmap(1098907648 bytes) failed; errno 12
190925  9:25:01 InnoDB: Completed initialization of buffer pool
190925  9:25:01 InnoDB: Fatal error: cannot allocate memory for the buffer pool
190925  9:25:01 [ERROR] Plugin ‘InnoDB’ init function returned error.
190925  9:25:01 [ERROR] Plugin ‘InnoDB’ registration as a STORAGE ENGINE failed.
190925  9:25:01 [ERROR] Unknown/unsupported storage engine: InnoDB
190925  9:25:01 [ERROR] Aborting

190925  9:25:01 [Note] /usr/local/mysql/bin/mysqld: Shutdown complete

查看内存显示  
[root@AY1305070924544 /]# free -m
             total       used       free     shared    buffers     cached
Mem:           995        928         66          0          6         19
-/+ buffers/cache:        903         91
Swap:            0          0          0

重启错误提示 

[root@AY1305070924544 /]# /etc/init.d/mysqld start
Starting MySQL. ERROR! The server quit without updating PID file (/var/mysql/data/AY1305070924544.pid).
[root@AY1305070924544 /]# /etc/init.d/mysqld restart
 ERROR! MySQL server PID file could not be found!
Starting MySQL. ERROR! The server quit without updating PID file (/var/mysql/data/AY1305070924544.pid).

这个其实日志里面说的很明白就是 mysql要占用内存的时候 物理内存不够用导致的 所有 vim /etc/my.cnf
[inonodb]
innodb_buffer_pool_size=64MB  把这个数值改小 高版本的默认是128mb  版本的默认是8Mb

MySQL 5.6 如何给ibdata1瘦身

前不久刚给ibdata1瘦身,发篇文章总结下。

ibdata1是MySQL使用InnoDB引擎时所产生的文件,其一般存储数据、索引、结构、缓冲数据、共享数据和重做日志等。因为ibdata1只增不减,长期操作数据库,可能会使其越来越大,而浪费空间。

加上使用InnoDB引擎时,没有添加innodb_file_per_table参数也是导致ibdata1过大的原因。

但InnoDB只增不减,也导致给ibdata1瘦身是件比较麻烦的事。

最大的我见过的是40多G的ibdata1文件,实际数据库差不多是20多G,在做了优化后,ibdata1缩小至20多G,所以说减肥还是有必要的。

首先,先略微说下innodb_file_per_table参数,使用该参数可使得InnoDB引擎转变为独立表空间模式(默认为共享表空间),也就是每个数据库的每个表都会生成一个数据空间,就像MyISAM引擎一样。

 
独立表空间优点就是每个表有独立空间,数据和索引都会存在自已的表空间中,可以实现单表在不同的数据库中移动。重要的是空间可以回收,而且不管日常怎么操作,表空间的碎片不会太严重的影响性能,优化表的速度也快,表文件出现问题不会大动干戈,只要修复对应表即可。缺点是单表占用的空间比共享表空间方式稍大,共享表空间在Insert操作上有一些优势。

所以没增加innodb_file_per_table参数的同学,建议还是加上吧。因为增加innodb_file_per_table参数,与我们后续给ibdata1瘦身并无冲突,而且对以后也只有好处。

说了这么多废话,言归正传。谈谈怎么给ibdata1瘦身,唯一的方法是就是备份整个数据库,然后删掉ibdata1和ib_logfile*,再恢复数据库,以此达到瘦身目的。当然了,操作数据库肯定是有风险的,而且也需要生产环境允许MySQL暂停写或访问。

简单的总结就是以下这几点:

1.在/etc/my.cnf中添加“innodb_force_recovery=4”使InnoDB成为只读表,这其实应该说是第一个坑。另外确定“innodb_data_file_path”参数限定的初始ibdata1大小在合理范围,一般稍大于现有数据大小。
2.启动MySQL,使用我给的工具备份除了mysql、information_schema和performance_schema的整个数据库。为以后顺利恢复数据做准备。
3.删除除了mysql、information_schema和performance_schema的整个数据库,这3个排除在外的其实也删不掉。
4.停止MySQL,删除ibdata1和ib_logfile*文件。
5.删除数据库目录中的mysql目录的innodb_index_stats.*、innodb_table_stats.*、slave_master_info.*、slave_relay_log_info.*、slave_worker_info.*文件,这5个是InnoDB的基础表(状态表),这是MySQL 5.6的坑,删除ibdata1后不会自动重建这5个表,而且如果不删除这些旧文件,还不可创建或重建新的。
6.在/etc/my.cnf把“innodb_force_recovery=4”去除。
7.启动MySQL,将第2步备份的数据库还原,然后用从MySQL 5.6导出来的InnoDB基础表备份还原回去重建(第5步删掉的)。
8.搞定,重启下MySQL,确保没有错误,没有异常。

必要的工具,在文末的Github地址下载。

下面详细说说每个步骤,首先是设置InnoDB为只读表,这还是比较必要的。可确保你的数据完整性、安全性。为何是坑呢,因为我遇到过没这样设置,导致后续恢复备份时,数据有异常。

具体操作,在/etc/my.cnf中添加“innodb_force_recovery=4”


[mysqld]

innodb_force_recovery = 4

如此便可,innodb_file_per_table也是在[mysqld]下添加。

innodb_force_recovery的值可以设置为1-6,大的数字包含其前面所有数字的影响。

1. (SRV_FORCE_IGNORE_CORRUPT):忽略检查到的corrupt页。
2. (SRV_FORCE_NO_BACKGROUND):阻止主线程的运行,如主线程需要执行full purge操作,会导致crash。
3. (SRV_FORCE_NO_TRX_UNDO):不执行事务回滚操作。
4. (SRV_FORCE_NO_IBUF_MERGE):不执行插入缓冲的合并操作。
5. (SRV_FORCE_NO_UNDO_LOG_SCAN):不查看重做日志,InnoDB存储引擎会将未提交的事务视为已提交。
6. (SRV_FORCE_NO_LOG_REDO):不执行前滚的操作。

接着呢,启动MySQL,备份整个数据库,一般我们会用

mysqldump –lock-all-tables –all-databases > all-dbs.sql
来完整备份数据库。但这样的话,就包含了mysql、information_schema和performance_schema这3个数据库,而在后续还原数据库,带着这3个数据库可能会出错(我有几次遇到过)。

所以我提供了shell脚本工具mysql_dump_all_db.sh,因为怕大家不像我是免密码操作MySQL的,在使用工具前,请先修改脚本中的MySQL帐号和密码,然后再通过

sh mysql_dump_all_db.sh
执行备份操作,备份好的文件,会存放在脚本运行所在目录。

这个工具默认排除mysql、information_schema和performance_schema这3个数据库,如果你有其他想排除的,可以直接修改脚本,增加其他想要排除的数据库。

完了之后呢,删除所有数据库,可以通过phpMyadmin或直接在shell操作MySQL删除,在shell下删除,可以在/tmp/DatabasesToDump.txt查看到所有数据库,由“mysql_dump_all_db.sh”生成。我一般在phpMyadmin删除,简单,不怕错。如你所见,mysql、information_schema和performance_schema这3个数据库是删不掉的,所以要排除,免得麻烦。

 
搞定后,就可以停止MySQL了。删除数据库目录的ibdata1和ib_logfile*文件,一般是在/usr/local/mysql/data,看你怎么配置的了。

接着,在该目录下的mysql目录(/usr/local/mysql/data/mysql)中,把innodb_index_stats.*、innodb_table_stats.*、slave_master_info.*、slave_relay_log_info.*、slave_worker_info.*共计10个文件删除,这些文件已经无用了,而且占着茅坑不拉屎。MySQL 5.6很煞笔的不会重建这5个表,如果你不删除他们,待会将无法重建或恢复这5个表,接着log一直在报错,死循环。所以要把这5个表的10个文件干掉。所以这个是个坑。

在/etc/my.cnf把“innodb_force_recovery=4”去除后,就可以启动MySQL了,这时候ibdata1和ib_logfile*文件会重建。噢,上帝,胜利在望,不要激动,让我们继续吧。

把刚才备份的所有数据库还原,用从MySQL 5.6导出来的InnoDB基础表备份还原回去重建。

我在后面的Github地址有提供,从全新 MySQL 5.6导出的,名字为“mysql_innodb_basic_tables.sql”的备份文件,通过它可以重建刚才删掉的5个InnoDB基础表。

还原数据库文件非常简单,不过我还是略微写下,照顾下小白,在shell下:

mysql < all-dbs.sql
mysql < mysql_innodb_basic_tables.sql
这样就OK了,如没有免密码操作权限,请自行添加-u和-p参数。

好的,做完这些,重启下MySQL,确保没有错误即可。这样就完成了对ibdata1的瘦身。

以上操作环境为:CentOS 6.6 x64、MySQL 5.6.25。

工具存放在Github中(原谅我的渣英文),见: https://github.com/kn007/Reduce-Shrink-Purge-the-ibdata1-file-in-MySQL

写这篇文章就是为了大家少走一点弯路,也把自己遇到的坑说一下。算是个总结,也是给后人的一些经验。原则上不提供技术支持,有问题请自行解决。另外毕竟是数据库,瘦身有风险,操作需谨慎。

xfs文件删除没有释放,系统重启还是没有释放

XFS文件系统管理常用命令记录

xfs_fsr /dev/vda1 单用户模式后,用碎片整理好恢复正常。

常用命令说明

mkfs.xfs
创建xfs文件系统
xfs_admin
调整XFS文件系统各种参数
xfs_copy
并行地拷贝XFS文件系统的内容到一个或多个目标系统中
xfs_db
调试或检测XFS文件系统
xfs_check
检测XFS文件系统完整性
xfs_bmap
查看一个文件的块映射
xfs_repair
尝试修复受损的XFS文件系统
xfs_fsr
碎片整理
xfs_quota
管理XFS文件系统的磁盘配额
xfs_metadump
导出XFS文件系统的元数据
xfs_growfs
扩展XFS文件系统大小
xfs_freeze
暂停/恢复XFS文件系统

创建XFS文件系统

使用 mkfs.xfs 可以将存储设备格式化为XFS格式

dd if=/dev/zero of=~/xfs.img bs=1M count=4096
mkfs.xfs ~/xfs.img

meta-data=/home/lujun9972/xfs.img isize=512    agcount=4, agsize=262144 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=0
data     =                       bsize=4096   blocks=1048576, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

但若原存储已经被格式化过,则 mkfs.xfs 会拒绝再次格式化

mkfs.xfs ~/xfs.img 2>&1 ||exit 0

mkfs.xfs: /home/lujun9972/xfs.img appears to contain an existing filesystem (xfs).
mkfs.xfs: Use the -f option to force overwrite.

这个时候需要用 -f 选项表示强行格式化

mkfs.xfs -f ~/xfs.img

meta-data=/home/lujun9972/xfs.img isize=512    agcount=4, agsize=262144 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=0
data     =                       bsize=4096   blocks=1048576, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

设置block大小

block是文件系统存储的最小单位,较大的block可以增加文件系统和单个文件的大小上限并加快大文件的读写速度,但是会浪费较多空间。而太小的block则相反。

我们可以在格式化时指定block的大小,XFS的大小最小为512字节,最大为64KB,默认为4K

在格式化时使用 -b size=block大小 来指定区块大小

mkfs.xfs -f -b size=1k ~/xfs.img

meta-data=/home/lujun9972/xfs.img isize=512    agcount=4, agsize=1048576 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=0
data     =                       bsize=1024   blocks=4194304, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=1024   blocks=10240, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

这里大小单位可以是”k”表示kb,或者”s”表示扇区数,一个扇区默认为512字节,但可以通过 -s 选项改变。

XFS允许目录使用比文件系统block更大的block,方法是使用 -n size=block大小

mkfs.xfs -f -b size=1k -n size=4k ~/xfs.img

meta-data=/home/lujun9972/xfs.img isize=512    agcount=4, agsize=1048576 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=0
data     =                       bsize=1024   blocks=4194304, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=1024   blocks=10240, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

日志大小

格式化XFS时,mkfs.xfs会根据文件系统的大小自动分配日志的大小。 日志大小介于512KB到128MB之间,但可以通过 -l size=日志大小 来设置,其中日志的单位可以是:

s
扇区
b
block
k
KB
m
MB
g
GB
t
TB
p
PB
e
EB
mkfs.xfs -f -l size=64m ~/xfs.img

meta-data=/home/lujun9972/xfs.img isize=512    agcount=4, agsize=262144 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=0
data     =                       bsize=4096   blocks=1048576, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=16384, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

设置文件系统标签

Label或者说Volume Name可以用来说明文件系统的用途,可以通过 -L 标签 来设置

mkfs.xfs -f -L TEST ~/xfs.img

meta-data=/home/lujun9972/xfs.img isize=512    agcount=4, agsize=262144 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=0
data     =                       bsize=4096   blocks=1048576, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

我们可以使用 xfs_admin 来查看当前的label

xfs_admin -l ~/xfs.img

label = "TEST"

挂载XFS文件系统

在挂载时,可以使用一些性能增强的选项来发掘XFS文件系统的性能

sudo mount -t xfs ~lujun9972/xfs.img /mnt -o noatime,nodiratime

其他常见的 -o 选项包括:

allocsize
延时分配时,预分配缓冲区的大小
discard / nodiscard
块设备是否自动回收空间
largeio
大块分配
nolargeio
尽量小块分配
noatime
读取文件时不更新访问时间
nodiratime
不更新目录的访问时间
norecovery
挂载时不运行日志恢复
logbufs
内存中的日志缓冲区数量
logbsize
内存中每个日志缓存区的大小

调整XFS文件系统参数

使用 xfs_admin 来调整XFS文件系统参数

卷标管理

设置卷标

xfs_admin -L "another_volume" ~/xfs.img

writing all SBs
xfs_admin: truncating label length from 14 to 12
new label = "another_volu"

查看卷标

xfs_admin -l ~/xfs.img

label = "another_volu"

UUID管理

传统上Linux在/etc/fstab中直接使用设备名称指定要挂载的存储设备。 然而设备名称会因为BIOS或硬件的改变而改变,引起混乱,因此现在Linux改用UUID来指定要挂载的存储设备。

查看指定设备的UUID

xfs_admin -u ~/xfs.img

UUID = aceeca47-82a0-47ce-a2e6-704569ebcbd4

设置设备的UUID

xfs_admin -U 12345678-9012-3456-7890-123456789012 ~/xfs.img

Clearing log and setting UUID
writing all SBs
new UUID = 12345678-9012-3456-7890-123456789012

你也可以给 -U 参数传递 generate 表示随机生成新的UUID

xfs_admin -U generate ~/xfs.img

Clearing log and setting UUID
writing all SBs
new UUID = 9618fe39-638d-41b0-9863-5b3b8daa9801

清除文件系统的UUID

xfs_admin -U nil ~/xfs.img

Clearing log and setting UUID
writing all SBs
new UUID = 00000000-0000-0000-0000-000000000000

扩展XFS文件系统的大小

XFS文件系统只能扩大,不能减少大小

扩容指定容量

sudo xfs_growfs -D 20G /mnt

扩展全部未用容量

sudo xfs_growfs -d /mnt

暂停/恢复XFS文件系统

xfs_freeze 命令可以停止对文件系统的访问并创建一个静态的磁盘镜像。

暂停XFS文件系统

sudo xfs_freeze -f /mnt

这个时候任何对文件系统的操作都会被挂起

恢复XFS文件系统

sudo xfs_freeze -u /mnt

修复XFS文件系统

sudo umount /mnt
xfs_repair ~lujun9972/xfs.img

碎片管理

查看碎片情况

xfs_db -c frag -r ~/xfs.img

actual 0, ideal 0, fragmentation factor 0.00%
Note, this number is largely meaningless.
Files on this filesystem average -nan extents per file

整理碎片

xfs_fsr ~/xfs.img

执行yum报 undefined symbol: CRYPTO_set_locking_callback 错误

源码安装了curl之后, 导致yum执行时报如下错误:

/usr/lib64/python2.6/site-packages/pycurl.so: undefined symbol: CRYPTO_set_locking_callback

是因为yum动态库使用了新安装libcurl库导致的。使用ldd查看动态库依赖关系:

ldd /usr/lib64/python2.6/site-packages/pycurl.so

可以发现libcurl.so.4 指向了新安装的libcurl。 

查找系统旧有的libcurl

find / -name “libcurl*”

/usr/lib64/libcurl.so.4 -> libcurl.so.4.1.1

/usr/local/lib/libcurl.so.4 -> libcurl.so.4.4.0

 

有两种方法解决:

1. 直接将/usr/local/lib/libcurl.so.4 软连接到旧有libcurl中

    rm  /usr/local/lib/libcurl.so.4

    ln -s /usr/lib64/libcurl.so.4.1.1 /usr/local/lib/libcurl.so.4

 

2. 设置LD_LIBRARY_PATH,  将旧有的libcurl路径放置在前面

export LD_LIBRARY_PATH=/usr/lib64:$LD_LIBRARY_PATH

Redis服务器设置密码后,使用/etc/init.d/redis restart出现(error) NOAUTH Authentication required.

Redis服务器设置密码后,使用/etc/init.d/redis restart出现(error) NOAUTH Authentication required.

#/etc/init.d/redis restart

Stopping …

OK
(error) NOAUTH Authentication required.
Waiting for Redis to shutdown …
Waiting for Redis to shutdown …
Waiting for Redis to shutdown …
Waiting for Redis to shutdown …
Waiting for Redis to shutdown …
Waiting for Redis to shutdown …
Waiting for Redis to shutdown …
Waiting for Redis to shutdown …
出现这样的错误信息,redis 这时是没有停止服务的。

可以使用ps -ef | grep redis  查进程号 然后kill 掉,如果在deamon下还需要去删除pid文件,有点繁琐。

解决办法:

用redis-cli 密码登陆(redis-cli -a  password)就OK了。

再用ps -ef | grep redis 可以看到redis进程已经正常退出。

修改redis服务脚本,加入如下所示的红色授权信息即可:

vi /etc/init.d/redis
$CLIEXEC -a “password” -p $REDISPORT shutdown

sqlite3数据库命令及数据库导入导出

1.  sqlite3 dbName.sqlite3  加载数据库,不存载就创建

2.  .help  帮助详解

    

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
sqlite> .help
.backup ?DBFILE      Backup DB (default "main") to FILE
.bail ON|OFF           Stop after hitting an error.  Default OFF
.databases             List names and files of attached databases
.dump ?TABLE? ...      Dump the database in an SQL text format
                         If TABLE specified, only dump tables matching
                         LIKE pattern TABLE.
.echo ON|OFF           Turn command echo on or off
.exit                  Exit this program
.explain ?ON|OFF?      Turn output mode suitable for EXPLAIN on or off.
                         With no args, it turns EXPLAIN on.
.header(s) ON|OFF      Turn display of headers on or off
.help                  Show this message
.import FILE TABLE     Import data from FILE into TABLE
.indices ?TABLE?       Show names of all indices
                         If TABLE specified, only show indices for tables
                         matching LIKE pattern TABLE.
.load FILE ?ENTRY?     Load an extension library
.log FILE|off          Turn logging on or off.  FILE can be stderr/stdout
.mode MODE ?TABLE?     Set output mode where MODE is one of:
                         csv      Comma-separated values
                         column   Left-aligned columns.  (See .width)
                         html     HTML <table> code
                         insert   SQL insert statements for TABLE
                         line     One value per line
                         list     Values delimited by .separator string
                         tabs     Tab-separated values
                         tcl      TCL list elements
.nullvalue STRING      Print STRING in place of NULL values
.output FILENAME       Send output to FILENAME
.output stdout         Send output to the screen
.prompt MAIN CONTINUE  Replace the standard prompts
.quit                  Exit this program
.read FILENAME         Execute SQL in FILENAME
.restore ?DBFILE     Restore content of DB (default "main") from FILE
.schema ?TABLE?        Show the CREATE statements
                         If TABLE specified, only show tables matching
                         LIKE pattern TABLE.
.separator STRING      Change separator used by output mode and .import
.show                  Show the current values for various settings
.stats ON|OFF          Turn stats on or off
.tables ?TABLE?        List names of tables
                         If TABLE specified, only list tables matching
                         LIKE pattern TABLE.
.timeout MS            Try opening locked tables for MS milliseconds
.width NUM1 NUM2 ...   Set column widths for "column" mode
.timer ON|OFF          Turn the CPU timer measurement on or off

3. 应用截图

加载

root@ubuntu:~/workspace/SVN_AUTH/db# sqlite3 development.sqlite3
SQLite version 3.7.2
Enter ".help" for instructions
Enter SQL statements terminated with a ";"

显示数据库

1
2
3
4
sqlite> .databases
seq  name             file                                                     
---  ---------------  ----------------------------------------------------------
0    main             /root/workspace/SVN_AUTH/db/development.sqlite3          

显示表

sqlite> .tables
applies            logs               repositories       users           
deps               permits            schema_migrations

显示表的内容

sqlite> .head on  #显示表头
sqlite> select * from users;
id|name|brief|group|dep_id|created_at|updated_at
1|3B-7-1-16  刘文民|liuwm|superadmin||2011-08-08 08:11:37.283136|2011-08-08 08:11:37.283136
3|3D-1-01  贾延平|jiayp|admin||2011-08-08 08:19:51.745947|2011-08-08 08:19:51.745947
4|3B-7-1-11 杜宏伟|duhw|||2011-08-08 08:33:51.496746|2011-08-08 08:33:51.496746
5|3B-2-14  苑辰|yuanc-a|emplooyee||2011-08-08 08:52:03.229173|2011-08-08 08:52:03.229173
6|3B-2-16  周四维|zhousw|||2011-08-08 08:54:21.134175|2011-08-08 08:54:21.134175
7|3B-2-12  施晟|shis|||2011-08-08 08:56:01.234077|2011-08-08 08:56:01.234077

显示创建表的脚本(不跟参数显示所有的)


sqlite的数据导入 导出

数据导入的来源可以是其他应用程序的输出,也可以是指定的文本文件,这里采用指定的文本文件。



   1. 首先,确定导入的数据源,这里是待导入的,按固定格式的文本文件。

   2. 然后,依照导入的文件格式,确定想导入的目标数据表,这个数据表如果没有,可以依照待导入的文本文件格式,创建一个相对应的数据表。

   3. 最后,执行.import命令,将文本文件中数据导入数据表中。





1. 数据源



   在/home/ywx/yu/sqlite/下,创建一个名为data.txt的文本文件,并输入以下数据,数据之间采用逗号隔开

  1. id,name,age,address,hobby

  2. 1,tom,24,beijing,football
  3. 2,liu,27,heibei,fotball
  4. 3,jim,26,shandong,football
  5. 4,han,28,beijing,football
  6. 5,meng,25,beijing,tennis

 

2. 目标数据表

    这里创建一张目标数据表,通过分析文本格式,这里需要3个字段,分别是id,name,age。但在数据类型选择时存在一个问题,id和age在文本文件中是按字符型存储的,而其实际在数据表中,最好要表示成整型,因此这里要涉及到一个字符型数据类型向整型数据类型转换的问题。

    在创建表时,将id和age的类型定义为整型,进行强制转换,如果在数据导入时,发现转换失败,可以将id和age类型改为文本型。



  1. ywx@ywx:~/yu/sqlite$ sqlite3 test.db

  2. SQLite version 3.7.7.1 20110628 17:39:05
  3. Enter “.help” for instructions
  4. Enter SQL statements terminated with a “;”
  5. sqlite> create table data_txt_table(id char(10),name char(10),age char(10),address varchar(15),hobby varchar (15));
  6. sqlite>



3. 导入命令



  1. sqlite> .separator “,” 

  2. sqlite> .import data.txt data_txt_table
  3. sqlite> select * from data_txt_table;
  4. id,name,age,address,hobby
  5. 1,tom,24,beijing,football
  6. 2,liu,27,heibei,fotball
  7. 3,jim,26,shandong,football
  8. 4,han,28,beijing,football
  9. 5,meng,25,beijing,tennis
  10. sqlite>



   这里需要注意一点,在数据导入之前,先要根据数据的具体分的格式,设置数据导入的间隔符,例如在文本数据中采用的是‘,’来间隔数据,因此应先调用.seperator 设置‘,’ 为间隔符。





2. 查看命令

  

  .schema 命令来查看指定的数据表的结构

  1. sqlite> .schema data_txt_table

  2. CREATE TABLE data_txt_table(id char(10),name char(10),age char(10),address varchar(15),hobby varchar (15));
  3. sqlite>



2. .tables 命令用来查看当前数据库的所有数据表



  1. sqlite> .tables

  2. data_txt_table
  3. sqlite>



3. databases 命令用来查看当前所有数据库



  1. sqlite> .databases

  2. seq name file 
  3.   
  4. 0 main /home/ywx/yu/sqlite/test.db 
  5. 1 temp





3. 数据导出



   数据导出也是一个常用到的操作,可以将指定表中的数据导出成SQL脚本,供其他数据库使用,还可以将指定的数据表中的数据完整定位到标准输出,也可以将指定数据库中的数据完整的导入到另一个指定数据库等,



1. 导出成指定的SQL脚本

   将sqlite中指定的数据表以SQL创建脚本的形式导出,具体命令



  1. ywx@ywx:~/yu/sqlite$ sqlite3 test.db

  2. SQLite version 3.7.7.1 20110628 17:39:05
  3. Enter “.help” for instructions
  4. Enter SQL statements terminated with a “;”
  5. sqlite> .output data.sql
  6. sqlite> .dump
  7. sqlite>

 

  1. ywx@ywx:~/yu/sqlite$ ll

  2. 总计 16
  3. drwxrxrx 2 ywx ywx 4096 20110813 23:15 ./
  4. drwxrxrx 7 ywx ywx 4096 20110813 20:53 ../
  5. rwrr 1 ywx ywx 602 20110813 23:17 data.sql
  6. rwrr 1 ywx ywx 2048 20110813 22:44 test.db



2. 数据库导出



  1. data.sql test.db

  2. ywx@ywx:~/yu/sqlite$ sqlite3 test.db “.dump” | sqlite3 test2.db
  3. ywx@ywx:~/yu/sqlite$ ll
  4. 总计 20
  5. drwxrxrx 2 ywx ywx 4096 20110813 23:20 ./
  6. drwxrxrx 7 ywx ywx 4096 20110813 20:53 ../
  7. rwrr 1 ywx ywx 602 20110813 23:17 data.sql
  8. rwrr 1 ywx ywx 2048 20110813 23:20 test2.db
  9. rwrr 1 ywx ywx 2048 20110813 22:44 test.db



3. 其他格式,如:htm格式输出



  1. ywx@ywx:~/yu/sqlite$ sqlite3 html test.db “select * from data_txt_table” > liu.htm

  2. ywx@ywx:~/yu/sqlite$ ls
  3. data.sql liu.htm test2.db test.db
  4. http://blog.chinaunix.net/uid-22666248-id-2182334.html