Go
语言和C
语言的一个很大的区别是,Go
语言只静态编译,做个测试:
$ cat testc.c
#include
int main( void )
{
printf("hello world \n");
return 0;
}
$ cat testgo.go
package main
import "fmt"
func main (){
fmt.Println("hello world")
}
$ gcc testc.c -o testc
$ go build testgo.go
$ ls -lh testc testgo
-rwxrwxr-x 1 oo2 oo2 8.2K Sep 25 10:39 testc
-rwxrwxr-x 1 oo2 oo2 2.0M Sep 25 10:39 testgo
一方面是Go
语言编译后的可执行文件大小比C
语言的大很多,
另一方面是C
语言的可执行文件需要依赖 glibc 动态库,
用ldd
命令可以看出来:
$ ldd testc
linux-vdso.so.1 (0x00007ffd57bcd000)
/lib/x86_64-linux-gnu/libc-2.27.so (0x00007fdd35e03000)
/lib64/ld-linux-x86-64.so.2 (0x00007fdd363f6000)
$ ldd testgo
not a dynamic executable
或者直接删除 glibc 动态库,C
可执行程序报错,而Go
的还能运行:
$ ./testc
hello world
$ ./testgo
hello world
$ ls -lh /lib/x86_64-linux-gnu/libc.so.6
lrwxrwxrwx 1 root root 12 Jun 4 17:25 /lib/x86_64-linux-gnu/libc.so.6 -> libc-2.27.so
$ sudo rm /lib/x86_64-linux-gnu/libc.so.6
$ ./testc
./testc: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory
$ ./testgo
hello world
这时候只有内部命令可以运行,外部命令,包括 ln
甚至最常用的 ls
命令也不能运行了:
$ type ls
ls is aliased to `ls --color=auto'
$ ln -s /lib/x86_64-linux-gnu/libc-2.27.so /lib/x86_64-linux-gnu/libc.so.6
ln: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory
$ ls
ls: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory
设置好 LD_PRELOAD
环境变量之后,ln
命令可以运行,但是 sudo
仍然不能运行
$ export LD_PRELOAD="/lib/x86_64-linux-gnu/libc-2.27.so"
$ ln -s /lib/x86_64-linux-gnu/libc-2.27.so /lib/x86_64-linux-gnu/libc.so.6
ln: failed to create symbolic link '/lib/x86_64-linux-gnu/libc.so.6': Permission denied
$ sudo ln -s /lib/x86_64-linux-gnu/libc-2.27.so /lib/x86_64-linux-gnu/libc.so.6
sudo: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory
只能靠 root
用户来重新创建软连接了:
# export LD_PRELOAD="/lib/x86_64-linux-gnu/libc-2.27.so"
# ln -s /lib/x86_64-linux-gnu/libc-2.27.so /lib/x86_64-linux-gnu/libc.so.6
所以用sudo
来rm
文件要小心,还是用 root
比较好。如果没有预先留一个打开的 root
终端,登录都登不进去。