直接嵌入c源代码到go代码里面
创新互联公司2013年至今,是专业互联网技术服务公司,拥有项目做网站、网站设计网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元自贡做网站,已为上家服务,为自贡各地企业和个人服务,联系电话:18980820575
package main
/*
#include stdio.h
void myhello(int i) {
printf("Hello C: %d\n", i);
}
*/
import "C"
import "fmt"
func main() {
C.myhello(C.int(12))
fmt.Println("Hello Go");
}
需要注意的是C代码必须放在注释里面
import "C"语句和前面的C代码之间不能有空行
运行结果
$ go build main.go ./main
Hello C: 12
Hello Go
分开c代码到单独文件
嵌在一起代码结构不是很好看,很多人包括我,还是喜欢把两个分开,放在不同的文件里面,显得干净,go源文件里面是go的源代码,c源文件里面是c的源代码。
$ ls
hello.c hello.h main.go
$ cat hello.h
void hello(int);
$ cat hello.c
#include stdio.h
void hello(int i) {
printf("Hello C: %d\n", i);
}
$ cat main.go
package main
// #include "hello.h"
import "C"
import "fmt"
func main() {
C.hello(C.int(12))
fmt.Println("Hello Go");
}
编译运行
$ go build ./main
Hello C: 12
Hello Go
编译成库文件
如果c文件比较多,最好还是能够编译成一个独立的库文件,然后go来调用库。
$ find mylib main
mylib
mylib/hello.h
mylib/hello.c
main
main/main.go
编译库文件
$ cd mylib
# gcc -fPIC -shared -o libhello.so hello.c
编译go程序
$ cd main
$ cat main.go
package main
// #cgo CFLAGS: -I../mylib
// #cgo LDFLAGS: -L../mylib -lhello
// #include "hello.h"
import "C"
import "fmt"
func main() {
C.hello(C.int(12))
fmt.Println("Hello Go");
}
$ go build main.go
运行
$ export LD_LIBRARY_PATH=../mylib
$ ./main
Hello C: 12
Hello Go
在我们的例子中,库文件是编译成动态库的,main程序链接的时候也是采用的动态库
$ ldd main
linux-vdso.so.1 = (0x00007fffc7968000)
libhello.so = ../mylib/libhello.so (0x00007f513684c000)
libpthread.so.0 = /lib64/libpthread.so.0 (0x00007f5136614000)
libc.so.6 = /lib64/libc.so.6 (0x00007f5136253000)
/lib64/ld-linux-x86-64.so.2 (0x000055d819227000)
理论上讲也是可以编译成整个一静态链接的可执行程序,由于我的机器上缺少静态链接的系统库,比如libc.a,所以只能编译成动态链接。
写作思路:根据题目要求,围绕猫进行描写。
I have a cat named Mimi. Its hair is as white as snow.
我有一只猫叫咪咪,它的毛像雪一样白。
I often play games with it, it makes me very happy, I regard it as a child.
我经常和它玩游戏,它让我很开心,我把它当成了一个小朋友。
Every morning, I say goodbye to it before I go to school.
每天早上,我都会在上学前和它道别。
Mimi will wave its front legs to me, it brings me a lot of happiness.
咪咪会向我挥舞它的前腿,它给我带来了很多快乐。
But it takes time and money to raise a cat. My parents and I spend a lot of time looking after it, feeding it and cleaning it.
但是养猫需要时间和金钱,我父母和我花了很多时间照顾它,喂它,打扫它。
We must clean the house from time to time, otherwise the cat will make them dirty and stink.
我们必须不时打扫房子,否则猫会把它们弄得又脏又臭。
一般命令
所谓一般命令,就是在一定时间内会执行完的命令。比如 grep, cat 等等。 执行命令的步骤是:连接,执行,获取结果
连接
连接包含了认证,可以使用 password 或者 sshkey 2种方式来认证。下面的示例为了简单,使用了密码认证的方式来完成连接。
import (
"fmt"
"time"
"golang.org/x/crypto/ssh"
)
func connect(user, password, host string, port int) (*ssh.Session, error) {
var (
auth []ssh.AuthMethod
addr string
clientConfig *ssh.ClientConfig
client *ssh.Client
session *ssh.Session
err error
)
// get auth method
auth = make([]ssh.AuthMethod, 0)
auth = append(auth, ssh.Password(password))
clientConfig = ssh.ClientConfig{
User: user,
Auth: auth,
Timeout: 30 * time.Second,
}
// connet to ssh
addr = fmt.Sprintf("%s:%d", host, port)
if client, err = ssh.Dial("tcp", addr, clientConfig); err != nil {
return nil, err
}
// create session
if session, err = client.NewSession(); err != nil {
return nil, err
}
return session, nil
}
连接的方法很简单,只要提供登录主机的 用户*, *密码*, *主机名或者IP*, *SSH端口
执行,命令获取结果
连接成功后,执行命令很简单
import (
"fmt"
"log"
"os"
"time"
"golang.org/x/crypto/ssh"
)
func main() {
session, err := connect("root", "xxxxx", "127.0.0.1", 22)
if err != nil {
log.Fatal(err)
}
defer session.Close()
session.Run("ls /; ls /abc")
}
上面代码运行之后,虽然命令正常执行了,但是没有正常输出的结果,也没有异常输出的结果。 要想显示结果,需要将 session 的 Stdout 和 Stderr 重定向 修改 func main 为如下:
func main() {
session, err := connect("root", "xxxxx", "127.0.0.1", 22)
if err != nil {
log.Fatal(err)
}
defer session.Close()
session.Stdout = os.Stdout
session.Stderr = os.Stderr
session.Run("ls /; ls /abc")
}
这样就能在屏幕上显示正常,异常的信息了。
交互式命令
上面的方式无法远程执行交互式命令,比如 top , 远程编辑一个文件,比如 vi /etc/nginx/nginx.conf 如果要支持交互式的命令,需要当前的terminal来接管远程的 PTY。
func main() {
session, err := connect("root", "olordjesus", "dockers.iotalabs.io", 2210)
if err != nil {
log.Fatal(err)
}
defer session.Close()
fd := int(os.Stdin.Fd())
oldState, err := terminal.MakeRaw(fd)
if err != nil {
panic(err)
}
defer terminal.Restore(fd, oldState)
// excute command
session.Stdout = os.Stdout
session.Stderr = os.Stderr
session.Stdin = os.Stdin
termWidth, termHeight, err := terminal.GetSize(fd)
if err != nil {
panic(err)
}
// Set up terminal modes
modes := ssh.TerminalModes{
ssh.ECHO: 1, // enable echoing
ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
}
// Request pseudo terminal
if err := session.RequestPty("xterm-256color", termHeight, termWidth, modes); err != nil {
log.Fatal(err)
}
session.Run("top")
}
MyCat 官方推荐使用 HAProxy 做 MyCat 的高可用负载均衡代理。
HAProxy 是一款提供高可用性、负载均衡以及基于 TCP(第四层)和 HTTP(第七层)应用的代理软件,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。
MyCat 服务主机上需要开放检测端口用来检测 mycat 服务的状态,提供给 HAProxy 对 MyCat 的服务状态进行检测判断。
检测 mycat 服务状态以通过xinetd 来实现, 使得HAProxy 可以用 httpchk 来检测 MyCat 的存活状态。
1、安装xinetd:
2、修改配置
检查是否有includedir /etc/xinetd.d,如果没有该配置需要加上:
3、检查 /etc/xinetd.d 目录
检查是否有 /etc/xinetd.d 目录,如果没有该目录需要加上:
4、配置存活状态检测
增加 MyCat 存活状态检测服务配置:
5、配置服务脚本
添加服务脚本/usr/local/bin/mycat_status:
6、添加可执行权限
7、配置启动服务
在 /etc/services 中加入 mycat_status 服务:
保存后重启:
9、开放端口
MyCat 服务主机的防火墙上打开 48700 端口:
设置开机启动:
[:[port]] 指定将客户端连接请求发往此服务器时的目标端口,此为可选项
[param*] 为此 server 设定的一系列参数,均为可选项,参数比较多,下面仅说明几个常用的参数:
weight: 权重,默认为 1,最大值为 256, 0 表示不参与负载均衡
backup: 设定为备用服务器,仅在负载均衡场景中的其他 server 均不可以启用此 server;
check: 启动对此 server 执行监控状态检查,其可以借助于额外的其他参数完成更精细的设定;
inter: 设定监控状态检查的时间间隔,单位为毫秒,默认为 2000,
也可以使用 fastinter 和 downinter 来根据服务器端专题优化此事件延迟
rise: 设置 server 从离线状态转换至正常状态需要检查的次数(不设置的情况下,默认值为 2);
fall: 设置 server 从正常状态转换至离线状态需要检查的次数(不设置的情况下,默认值为 3);
cookie: 为指定 server 设定 cookie 值,此处指定的值将会在请求入站时被检查,第一次为此值挑选的 server 将会被后续的请求所选中,其目的在于实现持久连接的功能;
maxconn: 指定此服务器接受的最大并发连接数,如果发往此服务器的连接数目高于此处指定的值,其将被放置于请求队列,以等待其他连接被释放。
默认情况下 haproxy 是没有日志的,如果有需要则配置系统的 syslog, 也就是 linux 系统中的 rsyslog 服务。
修改配置
增加haproxy日志配置文件
修改配置:
配置生效: