从删库到跑路

从删库到跑路 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑

最纯粹的技术 最高级的享受 欢迎关注公众号“MySQL从删库到跑路”

个人动态

从删库到跑路 发布了文章 · 2020-12-16

Shell脚本命令常用技巧

  • 如果一个命令只有一次输出,但想持续观察输出变化,使用watch -d -n1 'df -h'可行,df -h输出一次硬盘使用情况,用上面指令可以持续观察。-d表示相邻输出如果有差异要高亮标记,-n1表示每隔一秒执行一次df -h指令。
  • 观察网络接口流量sar -n DEV 1 200,DEV 1表示监控第一个网卡,200表示输出200次监控结果。
  • 日志文件很大,只想处理最后的十万行, tail -n 100000 access.log > accesspart.log, accesspart.log里就是最后的十万行。
  • $可以理解为取内容运算符 echo是打印 export是设置环境变量
  • 查看PATH变量值用echo ${PATH},查看PATH变量长度用echo ${#PATH}
  • pgrep ssh显示ssh进程的pid号
  • cat /proc/16119/environ | tr '\0' '\n' 查看pid号为16119的进程的环境变量,tr '\0' '\n'把每一项环境变量的末尾替换为换行符,使输出便于阅读
  • top显示各个进程资源占用情况。然后按shift+M,结果按内存占用由大到小排序。按shift+P,结果按cpu占用由大到小排序。
  • find指令后面必须有基本路径,-path后面的目录前后都要加*
  • shell中命令之间的空格很重要,空格分隔了不同的命令,\转义的一般都用空格与其他的指令隔离
  • shell常用变量:$1命令或脚本的第一个参数,第二个以此类推;$#参数数量;$0当前程序名称;$?上个命令的返回值;$$ 程序PID;$! 之前程序PID;$@以列表的方式打印所有参数;$*字符串的形式打印所有参数;
  • cd - 两个目录切换
  • echo "line containing a car pattern" | tr -s " " 把字符串的多个空格减少到一个空格
  • echo "line containing apattern " | tr -d 'n' 删除字符串中的n
  • echo "line containing apattern " | sed "s/c/x/g" 将字符串的c替换成x
  • name=${var%.}的含义是从右向左匹配%右侧的通配符. 并删除匹配结果,之后赋值给name %非贪婪 %%贪婪
  • name=${var#.}的含义是从左向右匹配#右侧的通配符. 并删除匹配结果,之后赋值给name #非贪婪 ##贪婪
  • tr ' ' '\n' 空格替换成\n,使得单行变多行。反过来多行可以变单行。
  • awk NR是当前行号,NF是当前行字段数量。$0是当前行的全部内容, $1等是当前行第1列的内容。
  • cat <<EOF >indeximg.xml ....EOF 把EOF之前的内容重定向到xml中
  • (子shell)& wait &表示脱离当前线程,wait表示全部完成才结束
  • ssh -p3456 user@IP 本服务器连接到IP服务器,端口号3456
  • 语句最后放一个&的意思是放置到后台运行
  • netstat -tnpul查看开放的端口和服务
  • 查看磁盘命令df=disk free du=disk usage
  • $while read line;do ... done<<file 使用方法 可以读取第一个参数文件
  • ps收集进程详细信息 结果各项含义:UID 用户ID; PID 进程ID; PPID 父进程ID; C CPU占用率; STIME 开始时间; TTY 开始此进程的TTY【终端】; TIME 此进程运行的总时间 ; CMD 命令名;
  • which查找某个命令的位置 whereis 包括手册的位置 file文件类型细节 whatis打印手册的某一行
  • kill -l信号列表 ; kill -s SIGNAL PID 发个信号给进程; killall process_name按程序名称杀; killall -u username process_name ; pkill 进程名; trap 处理信号函数 SIGINT(接收到SIGINT就运行处理函数)
  • $ hostname查看主机名 $ uname -n查看主机名 $ uname -a系统版本 $ uname -r内核版本 $ uname -m平台
  • cat /proc/cpuinfo【cpu信息】 cat /proc/meminfo【内存信息】 cat /proc/partitions【硬盘信息】
  • corn调度命令 【分 小时 天 月 星期】 *代表每次 $crontab -e会打开计划表 执行corn所使用的权限和执行命令的一致 crontab -r移除当前用户的cron表
  • cat<<! ....! 达到追加命令的效果,会将...一行一行的执行
  • ftp状态下执行lcd 在本地机上改变工作目录
  • MYTIME=\`date +"%Y%m%d %T"\` 反向单引号执行引号内语句,并将执行结果作为整体赋值给变量。普通单引号将语句作为字符串赋值给变量。
  • $ pstack pid号 显示进程栈跟踪 ,对处于错误状态的进程执行这个命令,打印的栈信息就是进程现在执行的代码,帮助定位bug
  • $strace -p pid号 查看进程正在使用哪些系统调用,可以看见系统调用的函数名称和报错信息。
  • $free -m 查看内存大小
  • $sysctl -p /etc/sysctl.conf重新载入内核参数,使配置生效
  • $ grep hhh * 会显示包含hhh的文件名和包含hhh的字符串
  • $ulimit -c unlimited 不限制core文件大小
查看原文

赞 0 收藏 0 评论 0

从删库到跑路 发布了文章 · 2020-12-15

C语言服务器编程必备常识

入门

  • 包含了正确的头文件只能编译通过,没链接正确的库链接会报错。
  • 一些常用的库gcc会自动链接。
  • 库的缺省路径/lib /usr/lib /usr/local/lib
  • 不知道某个函数在那个库可以nm -o /lib *.so | grep 函数名
  • man sin 会列出包含的头文件和链接的库名。man 2 sin 2表示系统调用,3表示c库函数
  • 一旦子进程被创建,父子进程一起从fork处被创建。创建子进程为了争夺资源。
  • 重定向用dup2函数
  • kill -l查看信号种类
  • pthread_mutex不跨进程,ipc中的信号量跨进程,但linux不支持无名信号量。信号灯的主要用途是保护临界资源。多进程访问共享内存,用信号量同步。
  • alarm(5)5秒后向自己发送SIGALARM信号,缺省处理是结束进程,不自定义就会结束进程。通过对信号集加减信号,确定信号屏蔽字。在信号处理程序被调用时,操作系统建立的新信号屏蔽字包括正在被递送的信号,如果此时这个信号再次发生,将阻塞到前一个处理完,多次发生不排队只处理一次。 sa_mask会被加到信号屏蔽字中。
  • netstat -an|grep A |grep ESTABLISHED | grep B,查看ip为A的服务器是否在端口B建立了连接
  • 由于我们的连接都是常连接,故可以按照客户端与服务器端建立的连接端口进行判断。
  • IP协议是网络层协议,主要发送数据包。UDP基于IP协议,用在传输层。TCP协议建立在IP协议之上,可靠的、按顺序发送的。
  • TCP连接三次握手:客户机向服务器发包。服务器给客户机回包。客户机收到包,向服务器发送确认信息完成连接。服务器收到确认信息也完成连接。
  • ioctl可以控制所有文件描述符的情况。
  • 循环服务器:UDP服务器,UDP是非面向连接的,没有一个客户机可以老是占着服务器。
  • TCP循环服务器一次只能处理一个,close后才能处理下一个。
  • TCP并发服务器:fork子进程来处理。创建子进程消耗资源。
  • 并发服务器:多路IO复用。
  • 当我们创建一个正常的TCP套接字的时候,我们只处理内容,不负责TCP头部和ip头部,自己创建头部使用setsockopt。
  • 网络程序一般是多进程加上多线程。
  • g++参数-pg产生gprof性能信息,gprof好像是g++自带的
  • (gdb)make使你能不退出gdb就能产生就重新产生可执行文件 , shell 不退出gdb就执行shell
  • file a.out可以在gdb模式下载入程序。
  • 服务器端:socket->bind->listen【建立监听队列,监听socket】->【返回连接socket】accept【从监听队列取请求,成功时返回新的socket,与传入的第一参数不同,标识被接受的这个连接】
  • 客户端:socket->connect

进阶

  • linux中代替数据库管理文件可能会出现文件数超过linux可管理数的问题。
  • tcpip协议族:上层协议使用下层协议提供的服务。
  • 应用层的东西最后需要在内核中实现,会需要应用空间和内核空间的切换。
  • IP数据太长要分片。IP协议的核心是数据报路由。路由表、跳转、自动更新。
  • socket含义ip:port。称其为socket地址。
  • 字节序是按字节考虑的,和位无关。cpu累加器一次装载4字节(32位机)。
  • 网络上传的一定是大端字节序,各主机按自身情况转化。java虚拟机采用大端字节序。
  • 不同输入调用两次函数,如果发现后面结果覆盖前面结果,说明函数不可重入。函数内部如果用静态变量存储结果,就不可重入。
  • 将一个地址和socket绑定称为给socket命名。0-1023端口普通用户不能使用,有默认用途。
  • accept只是从监听队列中取出连接,不论连接处于何种状态。connect(fd,..)一旦连接建立成功,fd就唯一标识了这个连接,客户端就可以读写fd和服务器通信。
  • 对socket执行close只减少连接数,fork会使引用数加1。无论如何都要终止连接用shutdown。
  • read和write同样适用于socket。用于TCP数据流的是send recv。UDP数据是recvfrom sendto。
  • 没有进程读管道的时候【例如close(fd[0])了】还往管道写数据将引发SIGPIPE。
  • 把STDOUT_FILENO关闭,dup(连接socket),这时dup返回最小可用描述符1【返回的文件描述符和原有描述符指向相同文件】,此时printf回返回给客户端,而不是打印在屏上。
  • sendfile将真实文件传给socket。splice用于在两个文件描述符间移动数据,零拷贝,用于socket和管道之间互相定向。tee用于两个管道之间复制数据。
  • IO处理单元是一个专门的接入服务器,它实现负载均衡。请求队列是系统内部各单元之间通信方式的抽象,一般实现为池。
  • 阻塞和非阻塞是对文件描述符而言的。非阻塞IO一般和IO通知机制一起使用,如IO复用或SIGIO信号。IO复用本身是阻塞的,提高效率是因为同时监听多个事件。
  • 同步就是协同步调,按预定的先后次序进行运行。处理客户连接就是读写描述符,就是IO,所以IO单元被定义为接入服务器。
  • 并发不适用于计算密集型,因为任务切换会降低效率,适用于IO密集型,如经常读写文件、访问数据库。
  • 池就是预先静态分配资源,到时可以快速使用。避免了对内核的频繁访问。提升性能方法:池、避免数据复制、上下文切换【线程数大于cpu数时】和锁。
  • 读写锁可以减少锁的粒度适用于读多写少的情况。
  • epoll需要使用一个额外的描述符维护事件表。 EPOLLONESHOT确保只有一个线程处理某个socket。
  • sigaction结构体中的sa_mask设置信号掩码,确切的说是在进程原有信号掩码的基础上增加信号掩码,以指定哪些信号不能发送给本进程。
  • sigset_t 每个元素的每个位表示一个信号,所以相同的信号只能表示一次。
  • 子进程有和父进程相同的信号掩码,但挂起信号集【发送但是被阻塞的信号】为空,就是说阻塞的信号是不可能发给子进程的。
  • 应用程序使用信号集sigset_t前,应调用sigemptyset或sigfillset一次,否则信号集初始状态不清楚。
  • 最小时间堆可以达到定时器的效果。
  • waitpid用NOHANG就是非阻塞的了。socketpair创建全双工管道的系统调用。
  • 对信号量的操作成为P(传递,进入临界区)V(释放,退出临界区)。最简单的二进制信号量,只有0和1.用一个普通变量模拟是不行的,因为检测和减1无法原子完成。
  • linux上的线程使用clone系统调用创建的进程模拟的。
  • 目前可以实现跨进程的线程同步
  • 被pthread_cancel的线程可以决定是否允许被取消以及如何取消。
  • 销毁一个已经加锁的互斥量将导致不可知的后果。互斥量属性设置中可以设置跨进程共享互斥量。pthread_mutexattr_setpshared()
  • 加锁-》pthread_cond_wait暗含解锁,确保能检测到条件变量的任何变化。
  • 有些函数不可重入主要是因为内部使用了静态变量。
  • 多线程程序中的一个线程调用fork,只复制调fork的那个线程。互斥量的状态也继承,此时容易出现死锁。
  • 所有线程共享信号处理函数,共享进程的信号。所以需要专门线程处理所有信号。
  • 进程池:典型的是3-10个。线程池中的线程数量应该和cpu数量差不多。通信【通信:传递数据】父子进程间可以使用管道,多线程间使用一个全局数据即可。
  • pthread_create当线程函数是类的成员函数时,必须为静态函数【确保没对象时也可以使用】,由于静态成员函数只能访问静态成员,要访问动态成员需要函数内部用单例或将类的对象作为参数传给函数。
  • SA_RESTART被信号中断的系统调用再信号处理结束后继续执行。
  • 将线程池或进程池中个数减少为1,便于调试逻辑。然后逐步增加数量,看同步。
  • 进程类[i].fd 通过给不同i的fd传递数据,调用不同的进程工作。m_sub_process[i].pid=fork()【fork了maxnum次】。
  • 线程池:线程函数一起都启动,启动后进入while(!stop)循环,不断的锁队列,取任务。

POSIX线程

  • 只有互斥量的主人能够解锁它。
  • 线程的堆栈受限。
  • 线程结束方式要么从线程函数return,要么调用pthread_exit,进入终止态,直到被分离或被连接。创建不需要连接的线程应该使用detachstate属性建立线程使其自动分离。
  • pthread_join会阻塞调用者,直到被join的线程结束,join返回被连接的线程也分离,所以只能被join一次,下一次就错误了。
  • 使用条件变量时必须保证如果有线程等待,则该线程等待后必然会收到信号(if/while)
  • 条件变量可以使线程处于等待状态而不消耗资源。条件变量必须跟一个互斥变量一起使用,因为条件变量就是共享的全局数据??【条件和锁结合共同保护共享数据】status = pthread_cond_wait(&alarm_cond, &alarm_mutex);
  • 没有条件变量,程序员可用使用轮询某个变量来实现停等-通知同步,但是非常消耗系统资源。
  • 如果确定线程不需要被Join, 则申明为Detached可以节省系统资源
  • pthread_self获得自身的ID,只能通过ID操作线程。main是主线程,主线程停止所有线程也停止,main中调用pthread_exit,这样进程就必须等待所有线程结束才能终止。
  • 通过向pthread_t(ID)=pthread_create传递线程函数地址和函数参数来创建线程。注意当前线程从pthread_create返回前,新创建的线程可能已经运行完毕了。
  • 舀水桶类似一个互斥量:桶用来保护“舀水”临界区【访问临界资源(共享数据?)的那段程序是临界区】。或者将桶理解为:用来确保一次只能由一个人舀水的不变量。
  • 在访问共享数据的代码段周围加锁互斥量,则一次只能有一个线程进入该代码段。
  • pthread_mutex_t表示互斥量,不能拷贝,可以拷贝指针。
  • 当调用pthread_mutex_lock时,如果互斥量已经被锁住,线程将被阻塞。调用pthread_mutex_trylock时不会阻塞,会返回EBASY,可以做其他的事情去。
  • 互斥量的本质是串行执行。
  • 解决死锁的两种方法:一,规定加锁顺序;二,trylock如果不行回退,解锁所有已加锁的互斥量
  • sched_yield()将处理器交给另一个等待处理的线程,如果没有等待处理的线程。立即返回。sleep()可以确保其他线程有机会运行。
  • 按照相反的顺序解锁,有助于减少线程做回退操作的可能。因为同一个线程函数中加锁顺序是一样的。对于不同的线程函数顺序应该不重要
  • 线程运行于解锁和阻塞之间时,其他线程才能改变共享数据状态。此时共享状态的改变,本线程是无法知道的。->需要条件变量。队列满,队列空,满空就是条件变量。
  • 动态初始化的条件变量需要pthread_cond_destroy来释放。静态初始化的不必释放。释放前确保其他线程不使用他。
  • 在阻塞线程之前,条件变量等待操作pthread_cond_wait将解锁互斥量,重新返回线程之前,会再次锁住互斥量。子线程只在pthread_cond_wait等待的短时间内可以加锁,修改共享数据,然后解锁。
  • pthread_cond_timedwait的意思就是我在这里等time时间,如果时间内条件变量变了,或者不变,我都要跳出while(谓词)的循环,按情况处理。
  • pthread_cond_wait和pthread_cond_signal必须同时发生才能成功。
  • 互斥量:条件变量是 一对多的关系
  • 当线程调用pthread_create时,她所能看到的内存值也是它建立的线程能看到的,之后的线程不一定能看到。
  • 线程解锁互斥量时所看到的的数据,也能被后来直接锁住相同互斥量的线程看到。解锁后写入的数据,不必被其他线程看见(因为那不是用来同步的数据,没必要所有人看见,同步就应该加锁)。
  • 线程终止,取消,从启动函数返回,pthread_exit时看到的数据,能够被连接该线程的其他线程看到。终止后写入的数据不会被看到。
  • 线程发信号或广播时看到的内存数据,可以被唤醒线程看到。之后写入的不会。
  • 线程分配的堆栈和堆空间是私有的,除非传给其他线程指针。register(寄存器变量)和auto变量(大部分变量默认auto)(static变量的生命期长)中的数据可随时读取,像在同步程序中一样
  • 两个处理器将各自的高速缓存中的数据写入主存的顺序是不一定的,即使写到相应高速缓存的顺序有先后之分。同一线程写数据也未必按照顺序刷新进内存,这使得其他线程读取结果不对。
  • 锁住互斥量->内存屏障->内存屏障->解锁互斥量
  • 使用线程的方式:流水线、工作组(工作线程在数据的不同部分操作)、C/S。
  • pthread_attr_setdetachstate (&_attr, PTHREAD_CREATE_DETACHED);说明在创建线程后,我们不在需要使用线程ID。
  • 不变量(Invariant):程序所做的一些假设,特别是指变量之间的关系。判定条件(Predicates):描述不变量状态的逻辑表达式。
  • pthread_kill(thdid, SIGTERM)给特定线程发信号
查看原文

赞 0 收藏 0 评论 0

从删库到跑路 发布了文章 · 2020-12-13

搞定MySQL安装难安装贵问题

背景

本方案解决了windows下安装MySQL过程繁琐的问题。
是真正的免安装绿色方法,不用配环境变量,不用执行install命令,不用配置my.ini文件。

步骤

下载

下载mysql-8.0.22-winx64.zip

解压到D盘

初始化

MySQL的bin目录下执行mysqld --initialize-insecure

命令成功生成data目录,同时生成无密码的root用户

启动MySQL

bin下执行mysqld --console

设置root密码

执行mysql -u root -p连入数据库,密码不用输入,直接按回车进入mysql>命令行
执行mysql> ALTER USER 'root'@'locoalhost' IDENTIFIED WITH mysql_native_password BY'123456';

用navicat测试连接


此时数据库只能在本机访问,无法远程访问。

设置远程访问

进入mysql库,修改root账号对应的host值。
update user set host = '%' where user = 'root';

必须执行flush privileges;才能生效

现在可以从另一台主机连接数据库了。

可能遇到的问题

如果执行过程报错

下载微软常用运行库合集,直接安装能解决问题

结论

方案为纯绿色方法,不修改window注册表的信息,当然也无法用net start mysql启动命令。好处是不污染系统环境,数据库坏了删除整个目录,重新解压一份MySQL重新执行本文过程就行了。

查看原文

赞 0 收藏 0 评论 0

从删库到跑路 发布了文章 · 2020-12-10

本文帮你在Unix玩转C语言

  • shell是一种特殊的应用程序(命令行解释器),他为运行其他应用程序提供了一个接口。
  • posix规范了操作系统是什么样
  • 每个进程都有一个工作目录(又叫当前目录),相对路径都是从工作目录开始解释。
  • Ctrl+D是文件结束字符
  • read读指定字节数;fgets是读取一行
  • 三个进程控制函数:fork exec waitpid。 waitpid【此函数获取信息,释放资源】父进程等待子进程终止,可以得到子进程何时终止。system函数是在exec外包了一层。
  • execlp要求参数以null结束,换行符不可以
  • 线程id只在它所属进程内起作用,在另一个进程中无意义,可以使用线程id引用相应的线程。
  • 一个用户可以属于多至16个组
  • ctrl+c中断键,ctrl+\退出键,等价于kill函数。kill(pid, SIGTERM)向另一进程发信号,发起信号的必须是该进程的所有者。
  • (gdb)set follow-fork-mode child使gdb进入子进程,事实证明不设置(默认调试父进程)这句无法进入pid==0的语句块。子进程exit后无法再设置断点gdb信息丢失,此时run可能启动的不是父进程而是孙进程。
  • fork会复制fork开始直到函数结束的代码【共享代码正文,但复制全部变量】
  • 日历时间:1970至今秒数,time_t类型用于保存这种时间。
  • 进程时间:cpu时间,clock_t类型用于保存这种时间。
  • 系统cpu时间是进程执行内核程序的时间。执行用户指令的时间是用户cpu时间。两者之和是cpu时间。时钟时间【墙上钟时间】,是进程运行的时间总量,和进程数有关。time ls【ls可换成任意程序名】 查看时间。
  • clock_t times(struct tms* buf)成功返回墙上钟时间【必须使用相对值,做差】
  • 库函数不一定调用系统调用。应用程序可以直接调用系统调用,也可以通过C库函数调用系统调用。
  • ISO C标准有24个头文件(包括stdlib.h,stdio.h)。
  • 接口即协议。
  • 很多程序需要为路径分配存储区
  • 守护进程:后台运行且不与终端相连接的一种进程。
  • 与文件或目录无关的选项用sysconf确定,与文件或目录有关的选项用pathconf,fpathconf确定。
  • unix系统的大多数文件I/O只需要用到5个函数:open close read write lseek,都是不带缓冲的I/O。不带缓冲指的是read write都调用内核的一个系统调用。不带缓冲的io不是iso c的组成部分,是posix的组成部分。
  • 对内核而言,所有的打开的文件都通过文件描述符(非负整数)引用。0 1 2 分别是输入 输出 错误 的描述符。文件描述符变化范围0-OPEN_MAX(表示每个进程可以打开OPEN_MAX个文件)。
  • open函数:int fileId【返回最小的未用文件描述符数值】 = open(tmpPtr->_fileName【文件名】,O_RDWR【读、写打开】|O_CREAT【如果不存在则创建】, 0666【配合O_CREATE指定新文件访问权限】);
  • close(fileId);关闭文件同时释放进程加在该文件上的所有记录锁。进程终止时内核自动关闭它打开的文件。
  • 返回文件偏移量【偏移量始终存在,读、写操作从它指向的位置开始】=lseek(fileId,offset【每一个打开的文件都有一个当前文件偏移量,默认0,除非指定O_APPEND】,SEEK_SET【将偏移量设为文件开始处offset字节】)
  • lseek返回-1说明文件描述符对应的文件是管道、fifo或网络套接字。某些设备允许负的偏移量。
  • od -c 文件名 【-c表示以字符方式打印文件内容】 ls -ls 查看文件占用多少个磁盘块
  • nRead【返回读到字节数】 = read(flag_fd【文件描述符】, buffer【读取数据到buffer中】, length【一次读取字节数】) 【成功返回前,偏移量增加读到的字节数】
  • int bytes_write【返回写入字节数】 = write(fileHandle,ptr,writeSize【写入字节数】) 【写操作从当前偏移量开始,成功后偏移量自动增加写入字节数】
  • 测量文件读写由于缓存机制,在第一次之后可能不准确。
  • 每个进程都有一张打开文件描述符表->文件表(当前文件偏移量)->v节点信息
  • 可能有多个文件描述符指向同一文件表项,多个文件表项指向一个v节点表。多进程读同一个文件没有问题,但是写同一个文件会有问题->原子操作。
  • open中用O_CREAT和O_EXCL可以将测试和创建合并为一个原子操作。原子操作指多步组成的操作要么执行完所有步骤,要么一步也不执行。
  • 先lseek再write不可能是原子操作。两个函数间内核可以挂起进程。
  • pread(..., off_t offset) pwrite(..., off_t offset) 相当于顺序调用lseek和read,与顺序调用的区别:无法中断、不更新文件指针
  • O_APPEND方式打开文件,每次write,文件偏移量自动定位到文件尾。
  • 新的文件描述符 = dup(int filedes) dup2(int filedes【被复制】,int filedes2【指定数值】) 复制现存的文件描述符,与参数filedes共享同一个文件表项。fcntl(..)也可以复制文件描述符。
  • sync将块缓冲区排入写队列,不等实际写磁盘。fsync对单一文件起作用,等写磁盘结束返回,更新属性。fdatasync只影响文件的数据部分。
  • fcntl(..)返回值和命令有关,可以返回文件状态,文件描述符。可以修改文件状态。
  • 5<>temp表示在文件描述符5上打开文件供读写。
  • 终端I/O是 ioctl的最大使用方面。
  • digit1 > &digit2表示要将digit1重定向至描述符2的同一个文件。
  • shell从左到右处理命令
  • struct stat sA【stat结构体包含磁盘号,所有者,访问修改时间等属性】; int retA【返回小于0表示文件不存在】 = stat(fileNameA.c_str(),&sA【stat函数将填写sA】); ls -l就是使用的stat(...)函数
  • lstat(...)的增强功能是检测符号链接
  • 文件类型信息包含在stat结构的st_mode成员中,有下面几种类型。

普通文件【包含某种数据的文件,数据是文本还是二进制对内核而言无区别,对文件内容的解释由处理该文件的应用程序进行。例外:二进制可执行文件遵守内核理解的统一格式】
目录文件【包含其他文件的名字以及指向与这些文件有关信息的指针】
块设备文件【磁盘,提供对设备带缓冲的访问】
字符设备文件【键盘,提供对设备不带缓冲的访问】
FIFO 又名管道文件,shell里的竖线 | 【用于进程间通信】
套接字【这种文件用于进程间的网络通信,也可用于一台机上进程间的非网络通信】
符号链接【这种文件类型指向另一个文件】

  • 进程间通信(IPC)对象也表示为文件:消息队列、信号量、共享存储对象。
  • 执行一个程序时exec(...)会保存有效用户ID和有效组ID。通常有效ID==实际ID。
  • 当文件的有效用户ID设置为文件所有者ID时,如果所有者为root,即使被一个普通用户执行,该进程也具有超级权限。
  • 文件访问权限:第一个规则是我们用名字打开一个文件时,对该名字包含的每一个目录,包括她可能隐含的当前工作目录(./)都应具有执行权限。对文件有适当的权限,取决于以何种方式打开。
  • 对目录的读权限使我们可以获得该目录所有文件名列表。对目录的执行权限使我们可以通过该目录,也就是【搜索】该目录,寻找一个特定的文件名。
  • 创建文件需要对目录有写权限和可执行权限。删除文件需要对目录有写和可执行权限【实际是减少文件i节点的一个连接数而已,文件本身还存在】,对文件本身不需要有读、写权限【删除对文件本身没读没写】。
  • 新文件的用户ID设置为进程的有效用户ID。新文件的组ID可以是:1.进程的有效组ID。2.它所在目录的组ID。
  • access(pathname, mode)按实际用户ID,和实际组ID进行访问权限测试。只有root能chown.
  • umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);设置进程的文件模式创建屏蔽字

creat("bar", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |S_IROTH | S_IWOTH)
先后运行上面两行的运行结果-rw------- bar
chmod("bar", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) fchmod(fildes, mod)
运行结果-rw-r--r-- bar

  • -rw-rwSrw- S表示设置组ID【有效用户ID和组ID】位已设置【有效用户ID变成文件所有者的ID】,同时,组执行位则未设置。
  • linux交换区==windows下虚拟内存
  • chmod a+t 目录 设置粘住位
  • 粘住位:可执行程序正文副本保存在交换区。目录设置了粘住位,只有对目录有写权限加上1.拥有文件;2.拥有目录;3.root三种之一 才可以删除或更名目录下的文件。
  • chown fchown lchown更改文件用户ID
  • truncate(pathnane, length) ftruncate(filedes, length) 截断文件或创建空洞
  • 磁盘可分为多个区,不同的区有不同的文件系统。
  • 目录项【目录/文件名】->i节点->实际数据块。多个目录项可以指向同一个i节点,例如软连接和目录本身指向的是同一块数据,就应该指向的是同一个i节点。mv只更改目录名,不移动实际数据。
  • link(existpath, newpath)创建一个新的目录项,增加链接数;unlink(pathname)删除目录项,将pathname所引用的文件链接数减1. 目录项删除后看不见文件,但文件仍有可能占据磁盘空间直至被内核删除。
  • ./a.out & 表示后台运行
  • 如果打开文件的进程数和链接数同时为0,内核会删除该文件。
  • remove(pathname)解除对一个目录或文件的链接。rename(oldname, newname)
  • 普通目录项和文件本身的关系是硬链接,她直接指向文件的i节点。符号链接是指向一个文件的间接指针,可以跨不同的文件系统。要注意函数是否跟随符号链接。
  • symlink(actualpath, sympath)创建符号链接。readlink(pathname, buf, bufsize)打开链接本身,并读链接中的名字。
  • ls -lt默认按文件修改时间排序,-u按访问时间,-c按更改状态时间。utime(pathname, times)更改文件的访问和更改时间。
  • mkdir(pathname, mode)创建一个新的空目录。rmdir(pathname)删除一个空目录。
  • DIR opendir(pathname) struct dirent readdir(DIR *dp) chdir(...)【当前工作目录是进程的一个属性,chdir只影响进程本身】 fchdir(...) getcwd(...)获得完整绝对路径
  • 标准I/O库【ISO C标准】文件操作围绕文件描述符,也可以理解成围绕流(stream)。当用标准io打开或创建一个文件时,我们已使一个流与文件关联。标准IO最终都要调用read,write。
  • FILE结构包含:文件描述符、缓冲区指针、缓冲区长度、当前缓冲区字节数以及出错标志。文件指针是FILE*
  • 标准输入输出的文件指针是stdin,stdout,stderr。io库提供缓冲的目的是减少使用read和write的调用次数。标准io函数通常调用malloc获得缓冲区。
  • setbuf(FILE , buf, mode ,size)更改缓冲类型。 fflus(FILE fp)此函数使该流所有未写的数据都被传送至内核。
  • FILE *fdopen(filedes, type)使已有的文件描述符和流关联。
  • FILE freopen(pathname, type, FILE restrict fp)在一个指定的流上打开文件,若流已打开,先关闭流。一般用于将指定文件打开为一个预定义的流:输入,输出,错误。
  • FILE *fopen(pathname, type【r+b,加号表示读和写】)打开一个指定的文件,b区分文本和二进制,对unix无用。 cache中用的都是open
  • int fclose(FILE *fp)关闭一个打开的流。
  • 读写结构fread fwrite
  • 一次一行fgets fputs
  • 一次一个字符getc(FILE fp) fgetc(FILE fp) getchar(void) getchar等价于getc(stdin)。 出错或到达文件尾,三个函数返回同样的值,为了区分需要ferror(FILE fp) feof(FILE fp) void clearerr(FILE *fp)
  • int ungetc(int c, FILE *fp)将字符再压送回流中。
  • 一次一个字符输出函数putc(int c, FILE) fputc(int c, FILE) putchar(int c)
  • 调用函数时间长于调用宏;一次系统调用比普通函数调用更费时间。
  • 每次一行io的函数:char fgets(buf,n,FILE)从指定流读。 char gets(buf)从标准输入读。 输出:fputs(str, FILE) puts(str)
  • 二进制IO:size_t fwrite(&struct[2], sizeof(struct), 4, FILE* fp) 将一个数组的第2-5号元素写在一个文件上
  • fread(..) 只能处理统一系统上的数据,异构系统通过网络互连时不行,不同系统间交换二进制数据需要使用较高级的协议。
  • 定位流:ftell(FILE) fseek(FILE, offset, whence【SEEK_SET】) rewind(FILE*) fgetpos(..) fsetpos(...) 文件描述符是用lseek
  • int fileno(FILE fp)获得文件描述符 , FILE tmpfile(void)创建临时文件
  • $TMPDIR=.. ./a.out 在程序名前指定环境变量
  • int printf(format,...)将格式化数据写到标准输出。 vprintf(format, va_list arg) vfprintf(...,va_list arg) vsprintf vsnprintf 可变参数表(...) 变成了arg
  • int fprintf(FILE* fp, format, ...)写至指定的流
  • int sprintf(buf, format)将格式化的字符串写入数组buf中,在数组尾端自动加null字节
  • int snprintf(buf, size_t n,format, ...) 与sprintf基本一样,n指定了缓冲区长度,超过就丢弃避免溢出
  • int scanf(format, ...) sscanf(cmdline【源】, "%s %s", opt[0], opt[1]【目的】)
  • int fscanf(FILE *fp, format, ...)
  • int sscanf(buf, format, ...) vscanf(format, va_list arg)等等
  • struct passwd getpwnam(const char name)获取口令文件项
  • struct tm结构用于保存时间的年月日的形式。
  • gettimeofday(struct timeval *res, NULL)微秒级
  • time_t time(time_t* calptr)返回当前时间,calptr不空,时间值放其中。
  • struct tm localtime(const time_t ptr)他和gmtime(..)的区别是他把日历时间转换为本地时区时间,gmtime转换成国际标准时间。
  • time_t mktime(struct tm* ptr)以本地时间作为参数,将其转换为time_t值【日历时间:1970至今】。
  • char asctime(struct tm)返回指向年月日字符串的指针。char ctime(time_t * prt)返回指向日历时间的指针。
  • size_t strftime(...)按格式控制时间字符串
  • timeval指定秒和微秒、timespec指定秒和纳秒
  • 正常终止一个程序:exit()默认包含关闭流操作【FILE存储区清0】 在main中exit(0)等价于return(0)
  • int atexit(void (*func)(void))登记的函数会被exit函数以相反的顺序调用。
  • 内核执行程序的唯一方法是exec。进程自愿终止的唯一方法exit【显式或隐式】。非自愿的需要给一个信号终止。
  • extern char **environ环境指针 getenv putenv 访问特定环境变量
  • a.out的符号表段、调试信息段、动态共享库链接表段不装载到进程执行的程序映像中。 size a.out 报告正文段、数据段、bss段的长度
  • cc -static hello1.c 阻止使用共享库。 cc默认使用共享库
  • void* malloc(size_t size)存储区初始值不确定
  • void* calloc(size_t nobj, size_t size)为指定数量指定长度的对象分配存储区,初始化为0
  • void realloc(void ptr, size_t newsize)更改以前的长度,新增部分初始值不确定,老部分保留内容。
  • void free(void* ptr)
  • goto语句不能跨越函数,setjump longjmp可以处理嵌套调用中出错情况【否则只能检查返回值逐层返回麻烦】。在希望返回的位置int setjmp(jmp_buf env【env为全局才多个函数可见】),出错位置int longjmp(env,8)。
  • "str1" "str2"等价于"str1str2"。为IO库分配缓冲区应全局静态或动态alloc分配。
  • 编译器进行优化时,它有时会取一些值的时候,直接从寄存器里进行存取,而不是从内存中获取,这种优化在单线程的程序中没有问题,但到了多线程程序中,由于多个线程是并发运行的,就有可能一个线程把某个公共的变量已经改变了,这时其余线程中寄存器【线程各自有寄存器】的值已经过时,但这个线程本身还不知道,以为没有改变,仍从寄存器里获取,就导致程序运行会出现未定义的行为。
  • 自动变量不想回滚,可以定义为volatite【易失】属性。易失属性告诉编译器不要优化,在其他地方会改变值,优化可能将这个变量一直放到寄存器中。
  • int getrlimit(int resource, struct rlimit *rlptr) setrlimit可以查询和更改资源限制。shell中的ulimit。
  • getpid getppid【获得父进程id】 getuid geteuid getgid getegid【有效组id】
  • pid_t fork(void) fork返回两次 clone,父返子,子返0.父子进程执行fork之后的代码,父子共享正文不共享数据,共享文件表和i节点。写时复制(copy-on-write)写时复制,只读时共用。
  • vfork在子进程调用exec或exit之前,他在父进程的空间中运行,调用exec或exit之后父进程才继续运行。
  • 标准IO库printf是带缓冲的。标准输出连到终端是行缓冲【打印】,否则是全缓冲。定向到文件是全缓冲
  • 信号可由进程自身产生【abort】、其他进程【kill(pidid,sig)】或内核产生。
  • 父进程提前终止的的子进程由init【init中默认有wait】进程领养。内核为每个终止的子进程保存了一定量的信息,父进程用wait或waitpid得到这些信息。
  • 一个长期运行的进程fork很多子进程,除非手动wait,否则会出现很多僵死进程。
  • pid_t wait(int statloc) pid_t waitpid(pid_t pid【等待pid号进程】, int statloc【指向终止状态】, int options)【成功返回进程id、0、失败返回-1】。 如果收到SIGCHLD信号调用wait,可以立刻返回,如果任意时刻调wait,可能会阻塞直到有一个子进程终止。
  • wait3 wait4比waitpid多了一个功能是最后一个参数会返回所有子进程使用资源情况的汇总。
  • 竞争条件:多进程处理共享数据,数据的结果和处理顺序有关。父等子死用wait,子等父死 【轮询】while(getppid() != 1) sleep(1);等于1是init进程id。为1说明父进程死了,被init接管了。
  • exec不创建新进程,进程ID不变。exec只是用一个全新的程序替换当前进程的正文、数据、队、栈。execl execv execle execve execlp execvp
  • 所有.c文件查找字符串abort的指令$ grep abort .//.c
  • 任何时候都可以调用int setuid(uid_t uid)做下两种操作:有效用户ID=实际用户ID;有效用户ID=保存的设置用户ID【exec复制有效用户ID得来的(一般是文件所有者?)】。设置用户ID的程序,fork后,exec之前要改回普通权限,不应使用system函数。
  • suspend $fg 作业控制

  • shell中awk实际是shell先fork->exec(awk)->wait来运行的。
  • char* getlogin(void)获取登录名。找到运行该程序的用户登录名getpwuid(getuid())
  • 网络登录telnetd进程fork,父负责网络连接的通信,子执行login,父子间通过伪终端相连接。
  • 进程组是一个或多个进程的集合。getpgid setpgid设置指定进程或调用进程的组ID。
  • 会话是一个或多个进程组的集合。进程调用pid_t setsid(void)建立一个新会话。进程是首进程、组长、断开所有控制终端。pid_t getsid(pid_t pid)返回会话首进程的进程组ID。
  • secureCRT是终端,对应前台进程组【终端(终端也是文件描述符)关联的进程】,控制进程组【shell】,后台进程组【&让其后台运行】,加在一起是会话。
  • 一个作业是几个进程的集合,通常是一个进程的管道线。vi main.c【前台启动了一个作业】 pr *.c | lpr & | make all & 【后台启动了两个作业,两个作业调用的所有进程都后台运行】
  • 终端驱动程序产生信号进而影响前台进程组的方法:中断字符ctrl+C 退出字符ctrl+\ 挂起字符 ctrl+Z。 可以用信号使后台作业暂停,fg %1 使1号作业转为前台作业
  • 进程属于进程组,进程组属于一个会话,会话可能有也可能没有控制终端。前台进程组ID是终端的属性,不是进程的属性。
  • 管道线的最后一个进程是shell的子进程,执行管道的其他命令都是最后一个进程的子进程。前端进程组ID==sessionID时说明他是后台进程。
  • 不是孤儿进程组的条件:该进程组中有一个进程,其父进程属于同一个会话的另一个组。
  • 信号SIGKILL SIGSTOP不能忽略,不能捕捉。
  • core文件复制进程终止时的存储映像。
  • kill命令和kill函数只是将一个信号送给一个进程或组,进程是否终止取决于信号的类型,以及进程是否安排了捕捉该信号。$kill -USR1 7216
  • void (signal(int signo, void (func)(int)))(int)成功返回信号以前的处理配置,失败返回SIG_ERR。不改变信号的处理方式,就不能确定信号当前的处理方式。func指定SIG_IGN或SIG_DEL表示忽略或默认处理。
  • exec使捕捉失效,捕捉函数的地址可能无意义。
  • 进程捕捉到信号执行信号处理函数func,执行完后执行发生信号时正在执行的代码【pause函数能使进程挂起直到捕捉到一个信号】。处理第一次信号后是否将信号动作复位为默认值?
  • read write部分数据时被中断算成功还是失败可以选择。
  • 在信号处理程序中调用一个不可重入函数,结果是不可预见的。
  • raise(int signo) == kill(getpid(), int signo) 进程将信号发送给其他进程需要权限。向一个不存在的进程发空信号,kill返回-1.
  • 进程ID会重新使用。
  • signal函数的语义与实现有关,最好使用sigaction函数。sigaction(signo【要检测或修改的具体动作的信号编号】, &act【非空则修改其动作】, &oact【非空则返回信号的上一个动作】)
  • sigemptyset(&act.sa_mask)【初始化由set指向的信号集清除其中所有信号】
  • 在处理一个给定的信号时,如果这种信号再次发生,通常并不将他们排队,会被阻塞到对前一个信号处理结束为止。阻塞结束后内核只传递这种信号一次。【屏蔽字为0代表没有信号阻塞,执行哪个信号的处理函数屏蔽哪个信号】
  • unix低速系统调用阻塞期间【磁盘IO一般不阻塞】如果接受到一个信号,则该低速系统调用被中断。
  • void abort(void)使异常程序终止。子进程终止会向父进程发送SIGCHLD信号。sig2str str2sig是信号编号和信号名相互转换函数。
  • 多线程程序在单处理器运行仍然能改善响应时间和吞吐量。
  • 线程ID只在它所属的进程环境中有效,因此可以不唯一。
  • pthread_t pthread_self(void)获得自身线程的ID。主线程可以用线程ID控制哪个线程处理哪些作业。新线程和主线程之间有竞争,使用主线程返回的线程id并不安全。线程ID如果很长那估计是地址。
  • 如果任一线程调用exit,_Exit,_exit整个进程就会终止。线程终止方式:1.启动函数返回。2被同进程其他线程取消【线程可以忽略取消】。3 pthread_exit
  • void pthread_exit(void rval_ptr) int pthread_join(pthread_t thread, void* rval_ptr【保存线程的终止状态】)【阻塞直到线程返回】
  • 线程里面声明的东西别往出带。线程从线程函数返回终止,清理程序就不被调用。waitpid==pthread_join。pthread_detach使线程分离【对线程终止状态不感兴趣】,分离线程终止时资源被回收,分离的线程无法pthread_join。
  • 加锁的一种场景:对引用计数加1、减1以及检查是否为0之前都要锁住互斥量。【引用数类似文件的link】
  • 读写锁以读模式锁住是共享模式【并发读】,以写模式锁住是独占模式【独自写】。
  • 线程的虚拟地址空间是多个线程共用,如果线程多,会不够用。递归类型互斥量可以递归加锁。
  • 线程和信号都涉及函数可重入的问题。信号:捕捉函数如果向全局数据写会错。线程:多个线程同时调用同一函数。每个线程有各自的信号屏蔽字。信号处理函数进程内共享。
  • errno被重新定义为线程私有数据。键用来保护线程私有数据。
  • 包含多线程的进程fork时只有fork的线程被复制进子进程,锁的情况无法控制,如果马上exec就可以避免。
  • pread(...)使偏移量的设置和数据读取成为一个原子操作。
  • ps -a【显示其他用户所拥有的进程状态】x【没有控制终端的进程状态】j【会话ID、进程组ID。。】
  • 创建守护进程两次fork,就不是会话首进程,不会取得控制终端。fork保证子进程不是进程组组长,可以setsid。
  • lockfile(fd)对文件加锁 lockf(lockfd, F_TLOCK, 0L)可以确保只有一个守护进程运行。
  • 低速系统调用是可能会使进程永远阻塞的一类系统调用。
  • 非阻塞IO:操作无法完成,立即出错返回【不停在那,以便进行下一步处理,类似trylock试加锁】。两种方法指定描述符为非阻塞IO:open时O_NONBLOCK;fcntl(fd, cmd, &lock)打开 O_NONBLOCK标志。
  • 记录锁==字节范围锁:当一个进程读或修改文件某部分时,可以阻止其他进程修改同一文件区。有些系统中文件的最后状态取决于写该文件的最后一个进程。
  • 同一进程可对同一字节范围重复加锁,新锁换老锁。可以测试另一个进程是否对某记录加锁。
  • 锁是与进程、文件两者相关联的。fork出的子进程不继承父进程对文件的锁【避免父子同时写一个文件】。exec新程序继承原程序的锁。
  • 某些unix提供系统调用跟踪特性。
  • STREAM:构造内核设备驱动程序和网络协议包的一种通用方法。
  • IO多路转接【两个描述符】:执行阻塞read,阻塞是对整个进程阻塞,如果多个通路【一般是无限循环读、写】想要相互不影响,就得fork多个进程,每个进程处理各自的文件描述符。用非阻塞read轮询描述符消耗cpu。
  • IO多路转接思想:构造一张描述符表,调用一个函数,直到表中描述符中的一个已经准备好IO时,该函数返回,告诉进程哪些描述符可以IO。主要用于终端IO和网络IO。select(0, NULL, NULL, NULL, &tv)相当于sleep了,精确到微秒。
  • 异步IO:基本思想,告诉内核,当一个描述符已准备好可以进行IO时,用一个信号通知它【它指应用程序】。系统V异步IO调ioctl设置信号处理,只对STREAMS设备和STREAMS管道起作用。 BSD异步IO设置信号SIGIO处理程序,调fcntl设置O_ASYNC文件为异步IO。只对终端和网络描述符有效。
  • 存储映射IO:【将一个给定文件映射到一个存储区域】unsigned char mmapBuf = (unsigned char)mmap(NULL【区域起始地址】, fileSize, PROT_READ【映射区可读】, MAP_SHARED ,fd【被映射文件】, 0【映射字节在文件中起始偏移量】) munmap((char*)mmapBuf, fileSize)【解除映射】 msync冲洗到磁盘
  • IPC【InterProcess Communication】:各种管道、消息队列、信号量、共享存储、套接字、STREAMS【仅后两种支持不同主机进程间通信】
  • 管道:半双工【数据只能在一个方向上流动】;只能在公共祖先的进程间使用,通常fork后父子间使用。int pipe(int filedes[2]) fork后f[0]<-【内核自动?】-f[1] 有两份,各关闭一个
  • sh -c cmdstring表示shell将扩展字符串中的特殊字符【*.c】。
  • ${PAGE:-more}如果PAGE已定义,使用,否则用more。
  • 对管道标准IO默认全缓冲。
  • 通过FIFO【命名管道】不相关的进程也能交换数据。int mkfifo(pathname, mode_t mode)类似于创建普通文件。
  • 创建IPC结构:msgget semget shmget 要指定一个键key_t。 ftok可由一个路径名和项目ID产生一个键key_t ftok(path, id)
  • msgctl semctl shmctl修改uid、gid、mode 三种IPC都有内置限制,可通过配置内核修改。 ipcs查看 ipcrm删除
  • msgrcv可以是非先进先出
  • 信号量的值代表对应资源是否可以使用。semop(_ID, buf[]【数组中操作要么都执行,要么都不执行】, 1)表示等待信号量、释放资源、获取资源。semctl取信号量信息、设置信号量信息。
  • 使用信号量【实际上是同步原语而不是IPC】,先创建一个包含一个成员的信号量集合,信号量值赋初值1.分配资源时sem_op为-1调用semop,释放资源sem_op为1调用semop。每次设置SEM_UNDO,以处理进程终止还有未释放资源的情况。
  • shmget既可以创建,也可以引用已有的【msgget一样】。 shmctl IPC_RMID减少引用数,不真正删除。shmid和pickey不一样,shmget返回值是shmid 。shmdt脱接不删除,引用数减一。
  • 套接字用于不同计算机上的进程相互通信,其它进程运行位置透明。可以采用许多网络协议,TCP/IP常见。
  • 创建一个套接字int socket(int domain【例如ipv4internet网域】, int type, int protocol)返回套接字文件描述符。
  • int shutdown(int sockfd, int how)禁止套接字上的输入输出。uint32_t htonl(uint32_t hostint32)等进行处理器字节序和网络字节序的转换。
  • inet_pton( AF_INET, host.c_str(), &m_addr.sin_addr)将文本字符串转换成网络字节序的二进制地址
  • poll select函数能检查文件描述符的状态,用来决定是否对文件描述符执行某种操作。
  • setsockopt(_sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeo, len)
  • int fattach(int fileds, const char* path)使STREAMS管道和文件系统中的一个名字关联。
  • unix域套接字用于同一机器上进程间通信。int ssocketpair(int domain, int type, int protocol, int sockfd[2])
  • 终端IO:函数tcgetattr tcsetattr 终端IO控制函数大多tc开头
  • 很多数据库实现都采用两个文件:索引文件和数据文件。
查看原文

赞 0 收藏 0 评论 0

从删库到跑路 发布了文章 · 2020-12-08

Windows下MySQL无法启动万能解决方案

MySQL启动报错

window10上安装了MySQL之前使用都是执行net start mysql
启动,执行net stop mysql关闭。
某天开始启动报错“MySQL 服务无法启动”,“请键入 NET HELPMSG 3523 以获得更多的帮助”。

如果再执行启动命令会报“服务正在启动或停止中,请稍候片刻后再试一次”。

解决方案

这种问题网上有

  • 修改配置文件my.ini
  • 删data目录下文件
  • 重装MySQL

等多种解决方法。
前两种方案没能解决我的问题。
至于重装MySQL,据我所知,已经安装过MySQL的windows电脑第二次安装MySQL,会有很多坑。如果不想折腾,这里有个快捷的办法,你可以试一试。

最简单的解决方案

mysqld --console命令

MySQL在window下的启动方式有两种:

  1. 以管理员权限打开cmd,执行net start mysql。
  2. 以管理员权限打开cmd,进入MySQL安装目录bin下,执行mysqld --console。

第一种启动方式不成功,可以按下面步骤换第二种方式试试。

第一步杀MySQL残留进程

换第二种方法启动之前,先把mysqld进程杀死。执行

tasklist| findstr "mysql"  

查看是否有mysqld进程。

如果有mysqld进程,执行

taskkill/f /t /im mysqld.exe  

杀死进程

第二步启动MySQL

到MySQL安装目录bin下,执行

mysqld --console

查看原文

赞 0 收藏 0 评论 0

从删库到跑路 收藏了问题 · 2020-12-01

在普通html页面中使用axios问题

我直接在html中引用了 从axios cdn上下载来的js文件 并在js文件尾部加入如下代码

var uuid, bmid, url;
bmid = 2//这里写部门id
url = 'http://192.168.1.106:1024/kffp'//分配服务器地址

uuid = localStorage.getItem("uuid");
console.log(typeof uuid);
if (typeof (uuid) == 'undefined' || typeof (uuid) == 'null' || typeof (uuid) == '' || uuid == null) {

    localStorage.setItem("uuid", randomString());
    this.uuid = localStorage.getItem("uuid");
}

axios.post(this.url, {
    uuid: this.uuid,
    bmid: this.bmid
})
    .then(function (response) {
        console.log(response.data);
        alert(JSON.stringify(response.data));
    })
    .catch(function (error) {
        console.log(error);
    });
    
    

然后访问html页面这段代码执行没问题,后来我把这段代码用 function 包裹起来了 因为我需要从html页面传参进来 变成

function kffphs(cc) {
var uuid, bmid, url;
bmid = 2//这里写部门id
url = 'http://192.168.1.106:1024/kffp'//分配服务器地址

uuid = localStorage.getItem("uuid");
console.log(typeof uuid);
if (typeof (uuid) == 'undefined' || typeof (uuid) == 'null' || typeof (uuid) == '' || uuid == null) {

    localStorage.setItem("uuid", randomString());
    this.uuid = localStorage.getItem("uuid");
}

axios.post(this.url, {
    uuid: this.uuid,
    bmid: this.bmid
})
    .then(function (response) {
        console.log(response.data);
        alert(JSON.stringify(response.data));
    })
    .catch(function (error) {
        console.log(error);
    });

};

变成这样了 然后html调用 kffphs(cc);报错 TypeError: Cannot read property 'protocol' of undefined 跟踪是在 console.log(error); 这行了 是哪里写错了

从删库到跑路 发布了文章 · 2020-11-22

大数据和Hadoop平台介绍

大数据和Hadoop平台介绍

定义

大数据是指其大小和复杂性无法通过现有常用的工具软件,以合理的成本,在可接受的时限内对其进行捕获、管理和处理的数据集。这些困难包括数据的收入、存储、搜索、共享、分析和可视化。大数据要满足三个基本特征(3V),数据量(volume)、数据多样性(variety)和高速(velocity)。数据量指大数据要处理的数据量一般达到TB甚至PB级别。数据多样性指处理的数据包括结构化数据、非结构化数据(视频、音频、网页)和半结构化数据(xml、html)。高速指大数据必须能够快速流入并且能得到快速处理。

大数据发展背景

数据爆炸。伴随信息技术的应用,全球数据量呈几何级数增长。过去几年间的数据总量超过了人类历史上的数据总和。芯片、摄像头、各自传感器遍布世界各个角落,原本不能被感知的事物都可以被监测。软硬件技术的不断进步,也为处理大数据创造的条件。

大数据的应用领域

  • 在公共领域,跨部门提供大数据服务,能大幅减少检索和处理时间。提高公共服务的效率。
  • 企业通过收集产品在使用中产生的海量数据,进行分析,可以改善产品性能。
  • 大数据能帮助企业对用户进行更加细化的区分,并针对用户的不同需求提供个性化的服务。这是营销和危机管理常用的办法。
  • 利用自动化算法支持或替代人工决策。对大数据的分析能极大改善决策效果,降低风险,并挖掘出其他方法无法发现的宝贵信息。
  • 商业模式、产品与服务创新。Netflix根据大数据分析结果,制作《纸牌屋》。

大数据研究课题

  1. 数据获取问题。包括哪些数据需要保存,哪些数据需要丢弃,如何可靠的存储我们需要的数据。
  2. 数据结构问题。微博博客是没有结构的数据,图像和视频在存储和显示方面具有结构,但是无法包含语义信息进行检索。如果将没有语义的内容转换为结构化的格式,并进行后续处理,是需要面对的另一项挑战。
  3. 数据集成问题。不同来源数据之间进行关联,才能充分发挥数据的作用。
  4. 数据分析、组织、抽取和建模
  5. 如何呈现分析结果

科技公司大数据产品

  • 谷歌:MapReduce
  • IBM:InfoSphere大数据分析平台
  • SAS:高性能分析服务器和SAS DataFlux数据流处理引擎
  • EMC:Greenplum 支持海量并行处理
  • Teradata:Aster Data 基于MapReduce,提供了多种统计软件包

大数据发展趋势

  • 数据资源化。大数据成为企业和社会关注的重要战略资源,并已经成为大家争相抢夺的焦点。
  • 与云计算深度结合。大数据离不开云处理,云处理为大数据提供弹性可拓展的基础服务。
  • 带动科学理论的突破。带动数据挖掘、机器学习、人工智能和数据科学等相关技术的发展。

大数据处理一般步骤

  1. 数据的收集。

第一个方式是抓取或者爬取。例如搜索引擎就是这么做的:它把网上的所有的信息都下 载到它的数据中心,然后你一搜才能搜出来。
第二个方式是推送,有很多终端可以帮我收集数据。比如说小米手环,可以将你每天跑 步的数据,心跳的数据,睡眠的数据都上传到数据中心里面。

  1. 数据的传输

一般会通过队列方式进行,因为数据量实在是太大了,数据必须经过处理才会有用。可系统处理不过来,只好排好队,慢慢处理。

  1. 数据的存储

存储要确保安全,不易丢失,高容错性。

  1. 数据的处理和分析

存储的数据是原始数据,原始数据多是杂乱无章的,有很多垃圾数据在里面,因而需要清洗和过滤,得到一些高质量的数据。对于高质量的数据,就可以进行分析,从而对数据进行分类,或者发现数据之间的相互关系,得到知识。

  1. 数据的检索和挖掘

使想要的信息容易被搜索到。挖掘信息之间的相互关系。

开源框架

因为大数据的这些特点,针对其收集、传输、存储、处理分析和检索使用产生了许多开源框架。
|功能|框架|
|--|--|
|文件存储|Hadoop HDFS、Tachyon、KFS|
|离线计算|Hadoop MapReduce、Spark|
|流式、实时计算|Storm、Spark Streaming、S4、Heron|
|K-V、NOSQL数据库|HBase、Redis、MongoDB|
|资源管理|YARN、Mesos|
|日志收集|Flume、Scribe、Logstash、Kibana|
|消息系统|Kafka、StormMQ、ZeroMQ、RabbitMQ|
|查询分析|Hive、Impala、Pig、Presto、Phoenix、SparkSQL、Drill、Flink、Kylin、Druid|
|分布式协调服务|Zookeeper|
|集群管理与监控|Ambari、Ganglia、Nagios、Cloudera Manager|
|数据挖掘、机器学习|Mahout、Spark MLLib|
|数据同步|Sqoop|
|任务调度|Oozie|

一般大数据平台的框架如下图

Hadoop HDFS和Hadoop MapReduce作为大数据存储和处理的开山鼻祖,大数据平台上都处于核心位置。下面介绍一下两个框架的基本原理。

Hadoop HDFS基本原理

HDFS全称Hadoop Distributed File System。HDFS是一个分布式文件系统,可以部署在一个服务器集群上。Java语言开发,可以部署在任何支撑java的机器上。
HDFS有几个基本概念NameNode、DataNode和block。
NameNode负责整个分布式文件系统的元数据管理,也就是文件路径名,数据block的ID以及存储位置等信息。还要记录一些事情,比如哪些节点是集群的一部分,某个block有几份副本等。

DataNode是实际存储文件数据的节点。DataNode会通过心跳和NameNode保持通信,如果DataNode超时未发送心跳,NameNode就会认为这个DataNode已经失效,立即查找这个DataNode上存储的block有哪些,以及这些block还存储在哪些服务器上,随后通知这些服务器再复制一份block到其他服务器上,保证HDFS存储的block备份数符合用户设置的数目,即使再有服务器宕机,也不会丢失数据。

Block是HDFS中的存储单元,文件被写入HDFS时,会被切分成多个block块,默认的块大小是128MB,每个数据块默认会有三个副本。

数据写入:首先将文件分成多个block,每个block会被写入三个DataNode中,写入哪三个DataNode中是由NameNode指定的,写入完成,NameNode会记录这些信息。同一个文件中不同的block可能会被写入完全不同的DataNode中。

数据读取:数据读取时按block读取。每一个block时,会从NameNode获取信息,知道从哪个DataNode中读取,一般是就近原则。所有该文件的block读取完成,构成完整的文件。
客户端和Datanode是同一个机器:距离为0 ,表示最近
客户端和Datanode是同一个机架的不同机器 :距离为2 ,稍微远一点
客户端和Datanode位于同一个数据中心的不同机架上 :距离为4,更远一点

Hadoop MapReduce基本原理

Hadoop MapReduce是一个分布式计算框架,其中的运算都可以在多个机器上并行进行。使用者只需要完成运算本身的编码,不需要关心并行计算的底层细节。
MapReduce背后的思想很简单,就是把一些数据通过Map来归类,通过Reduce来把同一类的数据进行处理。Map和reduce的过程都是利用集群的计算能力并行执行的。计算模型的核心是Map和Reduce函数,两个函数由用户自行实现。

把原始大数据集切割成小数据集时,通常小数据集小于等于HDFS的一个block的大小,这样一个小数据集位于一个物理机上,便于本地计算。Map和reduce各自的启动任务数量可以由用户指定。

上图表示一个MapReduce统计单词出现次数的过程,原始数据分割为4个子文件,对每个子文件按照用户的Map函数会产生<单词, 出现次数>的<k2,v2>形式的结果。然后把相同单词的<k2,v2>组合在一起构成<k2,List(v2)>的形式,作为Reduce函数的输入,相同的k2一定分发给相同的Reduce任务处理,例如单词lorem的所有计算都由第一个Reduce任务来完成。按照这个思想,即使要统计的文件数量上千万个,单词数量有几千个,但是通过MapReduce框架,只要集群机器数量够多,也是可以在可接受时间内计算完成的。

大数据行业应用

  • 互联网:定向广告、用户行为分析、内容推荐、搜索引擎优化
  • 金融:反洗钱、反欺诈、客户价值分析、目标市场客户聚类、偿还能力预测、股票投资组合趋势分析
  • 电信:业务设计优化、客户流失预测、网络质量优化
  • 医疗卫生:临床数据比对、决策支持、就诊行为分析、疾病模式分析
  • 公共安全:嫌疑人行为预测分析、恐怖活动检测、危险性分析、关系人分析
  • 智慧交通:整个传感器、GPS和健康视频等设备产生的海量数据,结合气象监测设备的天气状况数据、人口分布数据、移动通信数据,实现智能公共交通。

推广使用面临的挑战

  • 少数机构对数据绝对垄断,大部分数据集中在这些机构内部。就像罕见病数据,只有通过共享机制和平台,才能为患者提供帮助。
  • 大数据应用应该以尊重用户隐私为前提,同时如何兼顾数据的开放和创新,是大数据行业面临的一个重要问题。企业通过大数据来理解用户的特点和需求,需要充分尊重他们的隐私权。
  • 现有的大数据架构无法保证数据本身不被篡改,因而限制了需要建立信任和确权的应用场景。诸如信用类的数据,如果没有办法确保数据的真实有效性,则很难运用在相关机构的决策流程中。
查看原文

赞 0 收藏 0 评论 0

从删库到跑路 发布了文章 · 2020-11-22

真零基础Python开发web

Python开发web服务的优势是开发效率高,可能只需要java五分之一的代码量。
Python搭建web服务有许多框架,本文介绍Django和bottle两个框架。

Django

安装

首先,安装该框架

安装成功,版本是1.11.28. 框架的文件安装在\python27\Scripts目录下(搜索电脑中Python安装目录下的Scripts就对了)。

建立项目

先进入\python27\Scripts目录,建立项目jinanwx(名称随便起)

同一个目录下可以看到新建立工程的目录

开发自己模块

进入python27\Scripts\jinanwx\jinanwx。新建我们自己的模块

jgotest01.py里面写简单的代码如下

模块功能就是返回个json格式结果。

修改urls模块

然后需要改urls.py模块

目录文件如下

就这么简单,新建一个文件再修改一个文件,就成了。

启动服务

回到上一级目录启动服务

启动成功,浏览器访问试试

bottle

开发功能不是特别复杂的web服务,可以考虑使用bottle框架,它比Django轻量。bottle例子在Linux下演示。

安装

使用bottle框架首先安装。一个指令搞定。

# pip install bottle  

进入Python命令行import bottle,没报错就是成功了。

代码

我的web服务就一个文件bottleweb.py,代码如下,一些解释在代码的注释里

#coding=utf-8  
from bottle import (run, route, get, post, put, delete, request, hook, response, static_file, app)  
import json  
import MySQLdb #本例子需要操作数据库,否则可以不写这行,这个数据库包pip估计安装不会成功,我是用yum install MySQL-python成功的  
import sys  
reload(sys)    
sys.setdefaultencoding('utf8')  

import bottle  
app = bottle.default_app()#处理静态资源需要定义,没有静态资源可以不写这行  
#搭建vue脚手架前后台联调时要下面两个@hook内容,否则会报跨域访问资源的错误  
@hook('before_request')  
def validate():  
    REQUEST_METHOD = request.environ.get('REQUEST_METHOD')  

    HTTP_ACCESS_CONTROL_REQUEST_METHOD = request.environ.get('HTTP_ACCESS_CONTROL_REQUEST_METHOD')  
    if REQUEST_METHOD == 'OPTIONS' and HTTP_ACCESS_CONTROL_REQUEST_METHOD:  
        request.environ['REQUEST_METHOD'] = HTTP_ACCESS_CONTROL_REQUEST_METHOD  


@hook('after_request')  
def enable_cors():  
    response.headers['Access-Control-Allow-Origin'] = '*'  
    response.headers['Access-Control-Allow-Methods'] = 'GET,POST,PUT,DELETE,OPTIONS'  
    response.headers['Access-Control-Allow-Headers'] = '*'  

@route('/test2020/dist/<path>')#静态资源在web服务下的地址,没放前端的静态资源这几个route和app.route可以不写  
def stat(path):  
    return static_file(path, root='./dist/')  

@app.route('/test2020/dist/static/js/<path>')    
def js(path):  #这几个目录我写成这样是因为vue打包完后目录结构就是dist 里面static等等  
    return static_file(path, root='./dist/static/js/')  

@app.route('/test2020/dist/static/css/<path>')   
def css(path):   
    return static_file(path, root='./dist/static/css/')  
    
@get('/test2020/date')#返回某个表中的日期,看sql你就明白了  
def helloins():  
    db = MySQLdb.connect("127.0.0.1", "yourusername", "yourpassword", "yourDBname", charset='utf8' )  
    cursor = db.cursor()  
    sql = "select DISTINCT date from testtable"  
    print sql  
    cursor.execute(sql)  
    data = cursor.fetchall()  
    jsondata={}  
    results=[]  
    for row in data:  
        result = {}  
        result['DATE'] = row[0]  
        results.append(result)  
    jsondata['code']=0  
    jsondata['datas']=results  
    return jsondata  #返回json格式为了方便前端vue接收处理,其实返回各种类型都可以  
    
@get('/test2020/helloworld')  
def helloworld():  
    return 'hello world!'  
    
if __name__ == '__main__':  
    run(host='0.0.0.0', port=2020, debug=True, reloader=True)  

bottleweb.py所在目录执行

#python bottleweb.py

web服务就启动了。浏览器访问http://127.0.0.1:2020/test2020/helloworld看效果。

如果安装了MySQL数据库可以测试test2020/date的url是否能返回结果

数据库只要有下面的数据就可以

前端页面是这个样子的,给用户选择某个日期。

前端是用vue+vux来开发的,开发完打包打出的东西上传到代码中提到的dist静态资源目录下。
如果觉得上面的代码有点复杂,可以把所有route, app.route的东西删除,把/test2020/date语句块也删除,把@hook删除,MySQL的东西删除,前端的东西也完全不考虑,就是最简单的bottle web服务,相当于hello world。
建议尽量懂上面的代码,涉及了静态资源,数据库,是web服务必须的内容。

pip升级的坑

分享一个遇到的pip的问题,我Python版本很低2.6.6。本来通过安装yum的epel,已经成功安装了好用的pip。但是每次我用pip命令,最下方都会提示升级

You are using pip version 9.0.3, however version 20.0.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command

我执行了pip install --upgrade pip升级,然后pip指令就不能用了。而且升级了之后,在想安装回低版本的pip就没有对应的安装包了。yum只能找到20.0.2版本的(老版本会被覆盖难道?)。

http://bootstrap.pypa.io/2.6/get-pip.py  

下载了get-pip.py也无法安装成功。最后在上面的地址下载到了2.6版本的安装文件,才成功安装可以使用的pip。

总结

相比java,python开发web代码量少,需要安装的库少,如果能满足功能和性能要求,python可能是更好的选择。

查看原文

赞 0 收藏 0 评论 0

从删库到跑路 发布了文章 · 2020-11-21

爬虫基本功就这么点

文章分三个个部分

  1. 两个爬虫库requests和selenium如何使用
  2. html解析库BeautifulSoup如何使用
  3. 动态加载的网页数据用requests怎么抓

两个爬虫库

requests

假设windows下安装好了python和pip。
下面用pip安装爬虫库requests

如果提示pip版本低,不建议升级,升级后可能python本身版本低,导致pip指令报错。

进入Python命令行验证requests库是否能够使用

看到import requests和requests.get函数都没有报错,说明安装成功可以开发我们的第一个爬虫程序了!
将代码文件命名为test.py,用IDEL打开。

最简单的爬虫就这么几行!

  1. 引入requests库,
  2. 用get函数访问对应地址,
  3. 判定是否抓取成功的状态,r.text打印出抓取的数据。

然后菜单栏点击Run->Run Module 会弹出Python的命令行窗口,并且返回结果。我们访问的是腾讯发布新冠肺炎疫情的地址

如果没有IDEL,直接cmd命令行运行按照下面执行

selenium

selenium库会启动浏览器,用浏览器访问地址获取数据。下面我们演示用selenium抓取网页,并解析爬取的html数据中的信息。先安装selenium

接下来安装解析html需要的bs4和lxml。
安装bs4

安装lxml

要确保windows环境变量path的目录下有chromedriver

我d盘的instantclient_12_2已经加到path里了。所以chromedriver解压到这个目录。chromedriver不同的版本对应Chrome浏览器的不同版本,开始我下载的chromedriver对应Chrome浏览器的版本是71-75(图中最下面的),我的浏览器版本是80所以重新下载了一个才好使。
代码如下

Python执行过程中会弹出

浏览器也自动启动,访问目标地址

IDEL打印结果如下

HTML解析库BeautifulSoup

selenium例子中爬取数据后使用BeautifulSoup库对html进行解析,提取了感兴趣的部分。如果不解析,抓取的就是一整个html数据,有时也是xml数据,xml数据对标签的解析和html是一样的道理,两者都是<tag>来区分数据的。这种格式的数据结构一个页面一个样子,解析起来很麻烦。BeautifulSoup提供了强大的解析功能,可以帮助我们省去不少麻烦。
使用之前安装BeautifulSoup和lxml。
首先代码要引入这个库(参考上面selenium库代码)

from bs4 import BeautifulSoup  

然后,抓取

r = request.get(url)      
r.encoding='utf8'  
html=r.read() #urlopen获取的内容都在html中  
mysoup=BeautifulSoup(html, 'lxml') #html的信息都在mysoup中了   

假设我们对html中的如下部分数据感兴趣

<data>  
        <day>20200214</day>  
        <id>1</id>  
        <rank>11</rank>  
        <name>张三</name>  
    </data>  
    <data>  
        <day>20200214</day>  
        <id>4</id>  
        <rank>17</rank>  
        <name>李斯</name>  
    </data>  

首先要找到tag标签为<data>的数据,而这类数据不止一条,我们以两条为例。那么需要用到beautifulsoup的find_all函数,返回的结果应该是两个<data>数据。当处理每一个<data>数据时,里面的<id><name>等标签都是唯一的,这时使用find函数。

mysoup=BeautifulSoup(html, 'lxml')    
data_list=mysoup.find_all('data')  
for data in data_list:#list应该有两个元素  
    day = data.find('day').get_text() #get_text是获取字符串,可以用.string代替  
    id = data.find('id').get_text()  
    rank = data.find('rank').get_text()  
    name = data.find('name').get_text()  
    #print name  可以print测试解析结果  

这是beautifulsoup最简单的用法,find和find_all不仅可以按照标签的名字定位元素,还可以按照class,style等各种属性,以及文本内容text作为条件来查找你感兴趣的内容,非常强大。

requests库如何抓取网页的动态加载数据

还是以新冠肺炎的疫情统计网页为例。本文开头requests例子最后打印的结果里面只有标题、栏目名称之类的,没有累计确诊、累计死亡等等的数据。因为这个页面的数据是动态加载上去的,不是静态的html页面。需要按照我上面写的步骤来获取数据,关键是获得URL和对应参数formdata。下面以火狐浏览器讲讲如何获得这两个数据。
肺炎页面右键,出现的菜单选择检查元素。

点击上图红色箭头网络选项,然后刷新页面。如下,

这里会出现很多网络传输记录,观察最右侧红框“大小”那列,这列表示这个http请求传输的数据量大小,动态加载的数据一般数据量会比其它页面元素的传输大,119kb相比其它按字节计算的算是很大的数据了,当然网页的装饰图片有的也很大,这个需要按照文件类型那列来甄别。

url带参数

然后点击域名列对应那行,如下

可以在消息头中看见请求网址,url的尾部问号后面已经把参数写上了。
途中url解释,name是disease_h5,callback是页面回调函数,我们不需要有回调动作,所以设置为空,_对应的是时间戳(Python很容易获得时间戳的),因为查询肺炎患者数量和时间是紧密相关的。
我们如果使用带参数的URL,那么就用

url='网址/g2/getOnsInfo?name=disease_h5&callback=&_=%d'%int(stamp*1000)     
requests.get(url)   

url和参数分离

点击参数可以看见url对应的参数

如果使用参数和url分离的形式那么
那么就这样

url="网址/g2/getOnsInfo"  

formdata = {'name': 'disease_h5',   
'callback': '',   
'_': 当前时间戳    
}    

requests.get(url, formdata)  

找url和参数需要耐心分析,才能正确甄别url和参数的含义,进行正确的编程实现。参数是否可以空,是否可以硬编码写死,是否有特殊要求,比较依赖经验。

总结

学完本文,阅读爬虫代码就很容易了,所有代码都是为了成功get到url做的准备以及抓到数据之后的解析而已。
有的url很简单,返回一个.dat文件,里面直接就是json格式的数据。有的需要设置大量参数,才能获得,而且获得的是html格式的,需要解析才能提取数据。
爬到的数据可以存入数据库,写入文件,也可以现抓现展示不存储。

查看原文

赞 0 收藏 0 评论 0

从删库到跑路 发布了文章 · 2020-11-18

会装虚拟机,删库不用跑

VBOX

Oracle VirtualBox是由德国InnoTek软件公司出品的虚拟机软件,现在则由甲骨文公司进行开发,是甲骨文公司xVM虚拟化平台技术的一部分。它提供用户在32位或64位的Windows、Solaris及Linux 操作系统上虚拟其它x86的操作系统。用户可以在VirtualBox上安装并且运行Solaris、Windows、DOS、Linux、OS/2 Warp、OpenBSD及FreeBSD等系统作为客户端操作系统。
VBox没有vmware易上手,特别是网络配置对于新手比较劝退。但优点是占用资源少,不用破解。如果你电脑配置不高,vmware开虚拟机卡顿,或者不想破解vmware,建议改用vbox。

本文内容

本文演示利用vbox安装Linux虚拟机,并配置网络,达到

  1. 使Linux既能访问外网,
  2. 也能和宿主机互相访问,
  3. 并且多个虚拟机之间也是互通的。

配置过程

按照文中步骤,并且vbox和Linux版本与文中一致一定能配置成功。
过程分三步

  1. 给虚拟机配置硬件参数
  2. 安装Linux系统
  3. 配置网络

硬件配置

安装vbox,一路默认点击下一步。中途会出现中断网络连接的警告,不用管继续安装。安装完成打开,点击新建,开始安装Linux虚拟机。

名称随便起,类型和版本按照iso文件实际情况选择

内存大小默认

创建虚拟硬盘默认

文件类型默认

最求速度,选择固定大小

硬盘我设置16G,默认值太小了

建立过程需要等待几分钟

完成后可以看见左边出现计算机的名字,到这步相当于虚拟机的硬件有了。

安装Linux系统

上述操作完成相当于硬件有了,下一步安装操作系统。鼠标点击没有盘片,choose a disk file里选择Linux iso镜像文件

点击启动

选择第二行选项,全新安装系统

不需要检查,选跳过

语言选择英语

键盘选择USEnglish

选择第一项

虚拟机就选择不要数据,物理机要考虑原来磁盘的数据是否保留。

hostname随意起,建议不要包含特殊字符,否则将来安装某些软件时会有识别不了的问题

设定系统时间的界面很友好,

鼠标点击上海,时间会换到上海时间

下面设置密码

提示密码复杂度太低,选择依然使用

安装类型选择默认选项

选择write changes to disk

服务器类型选择basic server,这几种类型决定了是否安装数据库组件,是否安装图形界面等。根据需要选择。我这里只需要基本环境,所以选择第一个就可以。

然后进入安装Linux界面

安装完成选择重启

配置网络

输入用户和密码,进入系统,由于basic server 没有图形界面,所以都是命令行操作了。

查看ip,发现只有回环ip,这个ip只能自己访问自己,外网和宿主机肯定是不通的了。

vbox相比于vmware难用的地方就在于网络的配置,我试验了网上说的多个方法,最终成功配通了外网和宿主机。首先进入/etc/sysconfig/network-scripts,查看网络接口文件。只有一个ifcfg-eth0。

ifcfg-eth0文件里写有网卡的物理地址。我试验多次的结论是,将带有物理地址的网络接口设置为Host-only类型,负责和宿主机以及其它虚拟机通信。同时还要启用第二个网络连接,将第二个网络连接设置为“网络地址转换NAT”,负责访问外网。ifcfg-eth0对应的是网卡1,同时勾选启用网卡2。设置如下图

网卡1的配置

网卡2的配置

配置网卡1接口文件ifcfg-eth0时,需要配置ip地址,这个地址必须和vbox在宿主机的虚拟网卡地址处于同一个网段。所以要查看vbox虚拟网卡地址

配置ifcfg-eth0文件,按照如下修改,192.168.56是固定的,最后一位我写的3,实际可以随意

DEVICE=eth0HWADDR=08:00:27:BD:9E:0F
TYPE=Ethernet
UUID=e225f10f-4aee-4fe9-a4b6-83ca44940fa1
ONBOOT=yes
NM_CONTROLLED=yes
BOOTPROTO=static
IPADDR=192.168.56.3
NETMASK=255.255.255.0


配置ifcfg-eth1文件,按照如下修改,

DEVICE=eth1
NM_CONTROLLED=yes
ONBOOT=yes
BOOTPROTO=dhcp


重启网络服务

查看百度是否通

宿主机ping虚拟机

虚拟机ping宿主机

我又用vbox安装了一个Linux虚拟机,host-only网卡地址设为192.168.6.2,从192.168.6.3ping192.168.6.2

宿主机和虚拟机,虚拟机之间都是通的了。SSH工具连接,ftp连接也都没有问题,可以进行日常开发试验了。另外,vbox开3台虚拟机也都不卡顿,可以多装几个虚拟机组成集群模拟真实环境。最重要的可以执行rm -rf /* 了,这次不用跑路。

查看原文

赞 0 收藏 0 评论 0

认证与成就

  • 获得 2 次点赞
  • 获得 1 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 1 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2020-09-19
个人主页被 1.6k 人浏览