1. 题目:编写一个TCP服务器和客户端,基于TCP的并发远程shell
  2. 要求实现:
  3. )对于所有收到的客户端消息,作为命令行进行执行,
  4. 并且将命令行的输出结果返回给客户端
  5. )要求使用并发结构
  6. )实现关键代码
  7. 子进程执行命令
  8. numbytes = read(connfd, buf, );
  9. buf[numbytes] = '\0';
  10. sprintf(cmd, "%s > /tmp/cmd.txt", buf);
  11. system(cmd);
  12. fp = fopen("/tmp/cmd.txt", "r");
  13. numbytes = fread(cmd, , *, fp);
  14. cmd[numbytes] = '\0';
  15. fclose(fp);
  1. 核心代码展示
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <errno.h>
  6. #include <sys/types.h> /* See NOTES */
  7. #include <sys/socket.h>
  8. #include <netinet/in.h>
  9. #include <arpa/inet.h>
  10. #include <sys/select.h>
  11. #include <fcntl.h>
  12. #include <termios.h>
  13. #include <signal.h>
  14. #include "commsock.h"
  15.  
  16. #define MAXBUFSIZE 1020
  17.  
  18. //报文结构
  19. typedef struct _packet
  20. {
  21. int len;
  22. char buf[MAXBUFSIZE];
  23. } Packet;
  24.  
  25. /**
  26. * readn - 读取固定大小的字节
  27. * @fd:文件描述符
  28. * @buf:接收缓冲区
  29. * @count:指定读取字节数
  30. * 成功返回count,失败返回-1,对等方连接关闭返回<count
  31. * */
  32. int readn(int fd, void *buf, int count)
  33. {
  34. int nread = ;
  35. int lread = count;
  36. char *pbuf = (char *) buf;
  37. while (lread > )
  38. {
  39. do
  40. {
  41. nread = read(fd, pbuf, lread);
  42. } while (nread == - && errno == EINTR);
  43. if (nread == -)
  44. return -;
  45. else if (nread == )
  46. return count - lread;
  47. lread -= nread;
  48. pbuf += nread;
  49. }
  50. return count;
  51. }
  52.  
  53. /**
  54. * writen - 写固定大小字节数
  55. * @fd:文件描述符
  56. * @buf:写入缓冲区
  57. * @count:指定写入字节数
  58. * 成功返回count,失败返回-1
  59. * */
  60. int writen(int fd, void *buf, int count)
  61. {
  62. int lwrite = count;
  63. int nwrite = ;
  64. char *pbuf = (char *) buf;
  65. while (lwrite > )
  66. {
  67. do
  68. {
  69. nwrite = write(fd, pbuf, lwrite);
  70. } while (nwrite == - && errno == EINTR);
  71. if (nwrite == -)
  72. return -;
  73. lwrite -= nwrite;
  74. pbuf += nwrite;
  75. }
  76. return count;
  77. }
  78.  
  79. /**
  80. * read_timeout - 读超时检测函数,不含读操作
  81. * @fd:文件描述符
  82. * @wait_seconds:等待超时秒数,如果为0表示不检测超时
  83. * 成功返回0,失败返回-1,超时返回-1并且errno=ETIMEDOUT
  84. * */
  85. int read_timeout(int fd, unsigned int wait_seconds)
  86. {
  87. int ret = ;
  88. if (wait_seconds > )
  89. {
  90. fd_set readfds;
  91. FD_ZERO(&readfds);
  92. FD_SET(fd, &readfds);
  93. struct timeval timeout;
  94. timeout.tv_sec = wait_seconds;
  95. timeout.tv_usec = ;
  96. do
  97. {
  98. ret = select(fd + , &readfds, NULL, NULL, &timeout);
  99. } while (ret == - && errno == EINTR);
  100. //ret==-1
  101. if (ret == )
  102. {
  103. errno = ETIMEDOUT;
  104. ret = -;
  105. } else if (ret == )
  106. {
  107. ret = ;
  108. }
  109. }
  110. return ret;
  111. }
  112.  
  113. /**
  114. * write_timeout - 写超时检测函数,不含写操作
  115. * @fd:文件描述符
  116. * @wait_seconds:等待超时秒数,如果为0表示不检测超时
  117. * 成功返回0,失败返回-1,超时返回-1并且errno=ETIMEDOUT
  118. * */
  119. int write_timeout(int fd, unsigned int wait_seconds)
  120. {
  121. int ret = ;
  122. if (wait_seconds > )
  123. {
  124. fd_set writefds;
  125. FD_ZERO(&writefds);
  126. FD_SET(fd, &writefds);
  127. struct timeval timeout;
  128. timeout.tv_sec = wait_seconds;
  129. timeout.tv_usec = ;
  130. do
  131. {
  132. ret = select(fd + , NULL, &writefds, NULL, &timeout);
  133. } while (ret == - && errno == EINTR);
  134. //ret==-1
  135. if (ret == )
  136. {
  137. errno = ETIMEDOUT;
  138. ret = -;
  139. } else if (ret == )
  140. {
  141. ret = ;
  142. }
  143. }
  144. return ret;
  145. }
  146.  
  147. /**
  148. * activate_nonblock - 设置套接字非阻塞
  149. * @fd:文件描述符
  150. * 成功返回0,失败返回-1
  151. * */
  152. int activate_nonblock(int fd)
  153. {
  154. int ret = ;
  155. int flags = fcntl(fd, F_GETFL);
  156. if (flags == -)
  157. return -;
  158. flags = flags | O_NONBLOCK;
  159. ret = fcntl(fd, F_SETFL, flags);
  160. //ret==-1
  161. return ret;
  162. }
  163.  
  164. /**
  165. * deactivate_nonblock - 设置套接字阻塞
  166. * @fd:文件描述符
  167. * 成功返回0,失败返回-1
  168. * */
  169. int deactivate_nonblock(int fd)
  170. {
  171. int ret = ;
  172. int flags = fcntl(fd, F_GETFL);
  173. if (flags == -)
  174. return -;
  175. flags = flags & (~O_NONBLOCK);
  176. ret = fcntl(fd, F_SETFL, flags);
  177. return ret;
  178. }
  179.  
  180. /**
  181. * connect_timeout - 带超时的connect(函数内已执行connect)
  182. * @fd:文件描述符
  183. * @addr:服务器网络地址结构
  184. * @wait_seconds:等待超时秒数,如果为0表示不检测超时
  185. * 成功返回0,失败返回-1,超时返回-1并且errno=ETIMEDOUT
  186. * */
  187. int connect_timeout(int fd, struct sockaddr_in *addr, unsigned int wait_seconds)
  188. {
  189. int ret = ;
  190. if (wait_seconds > )
  191. {
  192. if (activate_nonblock(fd) == -)
  193. return -;
  194. }
  195. ret = connect(fd, (struct sockaddr *) addr, sizeof(struct sockaddr_in));
  196. if (ret == - && errno == EINPROGRESS)
  197. {
  198. fd_set writefds;
  199. FD_ZERO(&writefds);
  200. FD_SET(fd, &writefds);
  201. struct timeval timeout;
  202. timeout.tv_sec = wait_seconds;
  203. timeout.tv_usec = ;
  204. int nwrite = select(fd + , NULL, &writefds, NULL, &timeout);
  205. //nwrite==-1 此时ret==-1
  206. if (nwrite == )
  207. errno = ETIMEDOUT;
  208. else if (nwrite == )
  209. {
  210. int err = ;
  211. socklen_t len = sizeof(err);
  212. ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len);
  213. if (ret == )
  214. {
  215. if (err != )
  216. {
  217. errno = err;
  218. ret = -;
  219. }
  220. }
  221. }
  222. }
  223. if (wait_seconds > )
  224. {
  225. if (deactivate_nonblock(fd) == -)
  226. return -;
  227. }
  228. return ret;
  229. }
  230.  
  231. /**
  232. * sock_init - 初始化SOCKET环境
  233. * @connid:连接套接字
  234. * 成功返回0,失败返回错误码
  235. * */
  236. int sock_init(int *connid)
  237. {
  238. int ret = ;
  239. if (connid == NULL)
  240. {
  241. ret = SckParamErr;
  242. printf("cltsock_init() params not correct !\n");
  243. return ret;
  244. }
  245. //init
  246. ret = socket(AF_INET, SOCK_STREAM, );
  247. if (ret == -)
  248. {
  249. ret = SckBaseErr;
  250. perror("socket() err");
  251. return ret;
  252. } else
  253. {
  254. *connid = ret;
  255. ret = ;
  256. }
  257. return ret;
  258. }
  259.  
  260. /**
  261. * connect_server - 连接服务器
  262. * @connid:连接套接字
  263. * @port:端口号
  264. * @ipaddr:IP地址
  265. * @wait_seconds:等待超时秒数,如果为0表示不检测超时
  266. * 成功返回0,失败返回错误码
  267. * */
  268. int connect_server(int connid, int port, char *ipaddr,
  269. unsigned int wait_seconds)
  270. {
  271. int ret = ;
  272. if (connid < || port < || port > || ipaddr == NULL
  273. || wait_seconds < )
  274. {
  275. ret = SckParamErr;
  276. printf("cltsock_init() params not correct !\n");
  277. return ret;
  278. }
  279. struct sockaddr_in addr;
  280. addr.sin_family = AF_INET;
  281. addr.sin_port = htons();
  282. addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  283. ret = connect_timeout(connid, &addr, wait_seconds);
  284. if (ret == -)
  285. {
  286. if (errno == ETIMEDOUT)
  287. {
  288. ret = SckTimeOut;
  289. printf("connect_timeout() time out !\n");
  290. return ret;
  291. }
  292. ret = SckBaseErr;
  293. perror("connect_timeout() err");
  294. return ret;
  295. }
  296. return ret;
  297. }
  298.  
  299. /**
  300. * send_packet - 发送数据包
  301. * @fd:文件描述符
  302. * @pack:数据包
  303. * @buflen:数据包大小
  304. * @wait_seconds:等待超时秒数,如果为0表示不检测超时
  305. * 成功返回0,失败返回错误码
  306. * */
  307. int send_packet(int fd, Packet *pack, int buflen, unsigned int wait_seconds)
  308. {
  309. int ret = ;
  310. //可写检测
  311. ret = write_timeout(fd, wait_seconds);
  312. if (ret == -)
  313. {
  314. if (errno == ETIMEDOUT)
  315. {
  316. ret = SckTimeOut;
  317. printf("write_timeout() time out !\n");
  318. return ret;
  319. }
  320. ret = SckBaseErr;
  321. perror("write_timeout() err");
  322. return ret;
  323. }
  324. //发送数据
  325. ret = writen(fd, pack, buflen);
  326. if (ret != buflen)
  327. {
  328. ret = SckBaseErr;
  329. perror("writen() err");
  330. return ret;
  331. }else
  332. {
  333. ret=;
  334. }
  335. return ret;
  336. }
  337.  
  338. /**
  339. * send_packet - 接收数据包
  340. * @fd:文件描述符
  341. * @pack:数据包
  342. * @buflen:数据包大小
  343. * @wait_seconds:等待超时秒数,如果为0表示不检测超时
  344. * 成功返回0,失败返回错误码
  345. * */
  346. int recv_packet(int fd, Packet *pack, int *buflen, unsigned int wait_seconds)
  347. {
  348. int ret = ;
  349. //读超时检测
  350. ret = read_timeout(fd, wait_seconds);
  351. if (ret == -)
  352. {
  353. if (errno == ETIMEDOUT)
  354. {
  355. ret = SckTimeOut;
  356. printf("read_timeout() time out !\n");
  357. return ret;
  358. }
  359. ret = SckBaseErr;
  360. perror("read_timeout() err");
  361. return ret;
  362. }
  363. //获取数据长度
  364. int len = ;
  365. ret = readn(fd, &pack->len, );
  366. if (ret == -)
  367. {
  368. ret = SckBaseErr;
  369. perror("readn() err");
  370. return ret;
  371. } else if (ret < )
  372. {
  373. ret = SckPeerClosed;
  374. printf("peer is closed !\n");
  375. return ret;
  376. }
  377. //网络字节序转化成本地字节序
  378. len = ntohl(pack->len);
  379. //获取包体
  380. ret = readn(fd, pack->buf, len);
  381. if (ret == -)
  382. {
  383. ret = SckBaseErr;
  384. perror("readn() err");
  385. return ret;
  386. } else if (ret < len)
  387. {
  388. ret = SckPeerClosed;
  389. printf("peer is closed !\n");
  390. return ret;
  391. } else if (ret == len)
  392. ret = ;
  393. *buflen = len;
  394. return ret;
  395. }
  396.  
  397. /**
  398. * product_ser - 处理服务器消息
  399. * @fd:文件描述符
  400. * @wait_seconds:等待超时秒数,如果为0表示不检测超时
  401. * 成功返回0,失败返回错误码
  402. * */
  403. int product_ser(int fd, unsigned int wait_seconds)
  404. {
  405. int ret = ;
  406. Packet pack;
  407. int buflen = ;
  408. while ()
  409. {
  410. memset(&pack, , sizeof(pack));
  411. ret = recv_packet(fd, &pack, &buflen, wait_seconds);
  412. if (ret != )
  413. {
  414. return ret;
  415. }
  416. //已经完全接收服务器所有数据
  417. if (buflen == && strncmp(pack.buf, "end", ) == )
  418. {
  419. break;
  420. }
  421. //printf("数据包长度是%d;%s\n",buflen,pack.buf);
  422. fputs(pack.buf, stdout);
  423. }
  424. return ret;
  425. }
  426.  
  427. /**
  428. * run_clt - 运行客户端
  429. * @connid:连接套接字
  430. * @wait_seconds:等待超时秒数,如果为0表示不检测超时
  431. * 失败返回错误码
  432. * */
  433. int run_clt(int connid, unsigned int wait_seconds)
  434. {
  435. int ret = ;
  436. //安装信号
  437. if (signal(SIGPIPE, handler) == SIG_ERR)
  438. {
  439. ret = SckBaseErr;
  440. printf("signal() failed !\n");
  441. return ret;
  442. }
  443. Packet pack;
  444. memset(&pack, , sizeof(pack));
  445. int buflen = ;
  446. write(STDIN_FILENO,"请输入shell命令:",sizeof("请输入shell命令:"));
  447. while (fgets(pack.buf, MAXBUFSIZE, stdin) != NULL)
  448. {
  449. //去除\n
  450. buflen = strlen(pack.buf) - ;
  451. pack.len = htonl(buflen);
  452. //发送数据
  453. ret = send_packet(connid, &pack, buflen + , wait_seconds);
  454. if (ret != )
  455. {
  456. return ret;
  457. }
  458. memset(&pack, , sizeof(pack));
  459. //接收服务器数据
  460. ret = product_ser(connid, wait_seconds);
  461. if (ret != )
  462. return ret;
  463. write(STDIN_FILENO,"请输入shell命令:",sizeof("请输入shell命令:"));
  464. }
  465. return ret;
  466. }
  467.  
  468. /**
  469. * close_socket - 关闭连接
  470. * @fd:文件描述符
  471. * 成功返回0
  472. * */
  473. int close_socket(int fd)
  474. {
  475. int ret = ;
  476. close(fd);
  477. return ret;
  478. }
  479.  
  480. /*
  481. * clear_back - 退格键不回显
  482. * 成功返回0,失败返回错误码
  483. * */
  484. int clear_back()
  485. {
  486. int ret = ;
  487. struct termios term;
  488. memset(&term, , sizeof(term));
  489. //获取当前系统设置
  490. if (tcgetattr(STDIN_FILENO, &term) == -)
  491. {
  492. ret = SckBaseErr;
  493. perror("tcgetattr() err");
  494. return ret;
  495. }
  496. //修改系统设置
  497. term.c_cc[VERASE] = '\b';
  498. //立即生效
  499. if (tcsetattr(STDIN_FILENO, TCSANOW, &term) == -)
  500. {
  501. ret = SckBaseErr;
  502. perror("tcsetattr() err");
  503. return ret;
  504. }
  505. return ret;
  506. }
  507.  
  508. /**
  509. * listen_socket - 创建服务器监听套接字
  510. * @fd:套接字
  511. * @port:端口号
  512. * 成功返回0,失败返回错误码
  513. * */
  514. int listen_socket(int fd, int port)
  515. {
  516. int ret = ;
  517. if (port < || port < || port > )
  518. {
  519. ret = SckParamErr;
  520. printf("listen_socket() params not correct !\n");
  521. return ret;
  522. }
  523. //reuse addr
  524. int optval = ;
  525. ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
  526. if (ret == -)
  527. {
  528. ret = SckBaseErr;
  529. perror("setsockopt() err");
  530. return ret;
  531. }
  532. //bind
  533. struct sockaddr_in addr;
  534. addr.sin_family = AF_INET;
  535. addr.sin_port = htons(port);
  536. addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  537. ret = bind(fd, (struct sockaddr *) &addr, sizeof(addr));
  538. if (ret == -)
  539. {
  540. ret = SckBaseErr;
  541. perror("bind() err");
  542. return ret;
  543. }
  544. //listen
  545. ret = listen(fd, SOMAXCONN);
  546. if (ret == -)
  547. {
  548. ret = SckBaseErr;
  549. perror("listen() err");
  550. return ret;
  551. }
  552. return ret;
  553. }
  554.  
  555. /**
  556. * product_clt - 处理客户端信息
  557. * @fd:文件描述符
  558. * 成功返回0,失败返回错误码
  559. * */
  560. int product_clt(int fd)
  561. {
  562. int ret = ;
  563. //接收客户端信息
  564. Packet pack;
  565. memset(&pack, , sizeof(pack));
  566. int buflen = ;
  567. ret = recv_packet(fd, &pack, &buflen, );
  568. if (ret != )
  569. return ret;
  570. //重新拼接shell脚本
  571. char *path = "/home/test/1/cmdres.txt";
  572. char tempbuf[] = { };
  573. if (buflen > )
  574. {
  575. ret = SckBaseErr;
  576. printf("用户输入数据过长,服务器无法接收!\n");
  577. return ret;
  578. }
  579. sprintf(tempbuf, "%s > %s", pack.buf, path);
  580. //执行shell脚本
  581. system(tempbuf);
  582. //打开文件
  583. FILE *pfr = NULL;
  584. pfr = fopen(path, "r");
  585. if (pfr == NULL)
  586. {
  587. ret = SckBaseErr;
  588. perror("fopen() err");
  589. return ret;
  590. }
  591. memset(&pack, , sizeof(pack));
  592. //读文件
  593. while (fgets(pack.buf, MAXBUFSIZE, pfr) != NULL)
  594. {
  595. //每读取一次,发送一个数据包
  596. buflen = strlen(pack.buf);
  597. pack.len = htonl(buflen);
  598. ret = send_packet(fd, &pack, buflen + , );
  599. if (ret != )
  600. {
  601. printf("发送数据失败!");
  602. break;
  603. }
  604. memset(&pack, , sizeof(pack));
  605. }
  606. //关闭文件流
  607. if (pfr != NULL)
  608. {
  609. fclose(pfr);
  610. pfr = NULL;
  611. }
  612. //文件读取完毕之后,发送一个0数据包,告诉客户端数据已经发送完毕
  613. memset(&pack, , sizeof(pack));
  614. strcpy(pack.buf, "end");
  615. buflen = strlen(pack.buf);
  616. pack.len = htonl(buflen);
  617. ret = send_packet(fd, &pack, buflen + , );
  618. if(ret!=)
  619. {
  620. return ret;
  621. }
  622. //删除临时文件
  623. system("rm ../1/*");
  624. return ret;
  625. }
  626.  
  627. /**
  628. * handler - 信号捕捉函数
  629. * @sign:信号值
  630. * */
  631. void handler(int sign)
  632. {
  633. if (sign == SIGPIPE)
  634. {
  635. printf("accept SIGPIPE!\n");
  636. }
  637. }
  638.  
  639. /**
  640. * select_socket - select机制管理客户端连接
  641. * @fd:文件描述符
  642. * 失败返回错误码
  643. * */
  644. int select_socket(int fd)
  645. {
  646. int ret = ;
  647. //安装信号
  648. if (signal(SIGPIPE, handler) == SIG_ERR)
  649. {
  650. ret = SckBaseErr;
  651. printf("signal() failed !\n");
  652. return ret;
  653. }
  654. //定义客户端套接字临时变量
  655. int conn = ;
  656. struct sockaddr_in peeraddr;
  657. socklen_t peerlen = ;
  658. //已经处理的select事件
  659. int nread = ;
  660. //创建客户端连接池
  661. int cltpool[FD_SETSIZE] = { };
  662. //初始化连接池
  663. int i = ;
  664. for (i = ; i < FD_SETSIZE; i++)
  665. {
  666. cltpool[i] = -;
  667. }
  668. //定义数组尾部元素下标
  669. int maxindex = ;
  670. //定义最大的套接字(初始值是监听套接字)
  671. int maxfd = fd;
  672. //定义最新的套接字集合
  673. fd_set allsets;
  674. FD_ZERO(&allsets);
  675. //定义需要监听的套接字集合
  676. fd_set readfds;
  677. FD_ZERO(&readfds);
  678. //将监听套接字加入最新的套接字集合
  679. FD_SET(fd, &allsets);
  680. while ()
  681. {
  682. //将最新的套接字集合赋值给需要监听的套接字集合
  683. readfds = allsets;
  684. do
  685. {
  686. nread = select(maxfd + , &readfds, NULL, NULL, NULL);
  687. } while (nread == - && errno == EINTR); //屏蔽信号
  688. if (nread == -)
  689. {
  690. ret = SckBaseErr;
  691. perror("select() err");
  692. return ret;
  693. }
  694. //1.服务器监听套接字处理
  695. if (FD_ISSET(fd, &readfds))
  696. {
  697. //接收到客户端的连接
  698. memset(&peeraddr, , sizeof(peeraddr));
  699. peerlen = sizeof(peeraddr);
  700. conn = accept(fd, (struct sockaddr *) &peeraddr, &peerlen);
  701. if (conn == -)
  702. {
  703. ret = SckBaseErr;
  704. perror("accept() err");
  705. return ret;
  706. }
  707. //将客户端连接添加到连接池
  708. for (i = ; i < FD_SETSIZE; i++)
  709. {
  710. if (cltpool[i] == -)
  711. {
  712. if (i > maxindex)
  713. {
  714. maxindex = i;
  715. }
  716. cltpool[i] = conn;
  717. break;
  718. }
  719. }
  720. if (i == FD_SETSIZE)
  721. {
  722. ret = SckBaseErr;
  723. close(conn);
  724. printf("客户端连接池已满!\n");
  725. return ret;
  726. }
  727. if (conn > maxfd)
  728. maxfd = conn;
  729. //将该客户端套接字加入到最新套接字集合
  730. FD_SET(conn, &allsets);
  731. printf("server accept from :%s\n",inet_ntoa(peeraddr.sin_addr));
  732. if (--nread <= )
  733. continue;
  734. }
  735. //处理客户端请求
  736. if (nread <= )
  737. continue;
  738. for (i = ; i <= maxindex; i++)
  739. {
  740. if (cltpool[i] == -)
  741. continue;
  742. if (FD_ISSET(cltpool[i], &readfds))
  743. {
  744. //处理客户端请求
  745. ret = product_clt(cltpool[i]);
  746. if (ret != )
  747. {
  748. //从最新的套接字集合中删除
  749. FD_CLR(cltpool[i], &allsets);
  750. //处理请求失败,关闭客户端连接
  751. close(cltpool[i]);
  752. //从客户端连接池中清除
  753. cltpool[i] = -;
  754. break;
  755. }
  756. if (--nread <= )
  757. break;
  758. }
  759. }
  760. }
  761. return ret;
  762. }

Linux Linux程序练习十八的更多相关文章

  1. 漫谈程序员(十八)windows中的命令subst

    漫谈程序员(十八)windows中的命令subst 用法格式 一.subst [盘符] [路径]  将指定的路径替代盘符,该路径将作为驱动器使用 二.subst /d 解除替代 三.不加任何参数键入  ...

  2. Linux系列教程(十八)——Linux文件系统管理之文件系统常用命令

    通过前面两篇博客,我们介绍了Linux系统的权限管理.Linux权限管理之ACL权限 介绍了通过设定 ACL 权限,我们为某个用户指定某个文件的特定权限,这在Linux只能对于一个文件只能有所有者权限 ...

  3. Linux学习之CentOS(十八)-----恢复Ext3下被删除的文件与 使用grep恢复被删文件内容(转)

    前言 下面是这个教程将教你如何在Ext3的文件系统中恢复被rm掉的文件. 删除文件 假设我们有一个文件名叫 'test.txt' $ls -il test.txt 15 -rw-rw-r– 2 roo ...

  4. Linux经常使用命令(十八) - find概述

    Linux下find命令在文件夹结构中搜索文件,并运行指定的操作.Linux下find命令提供了相当多的查找条件,功能非常强大.由于find具有强大的功能,所以它的选项也非常多.当中大部分选项都值得我 ...

  5. Linux 入门记录:十八、Linux 系统启动流程 + 单用户修改 root 密码 + GRUB 加密

    一.系统启动流程 一般来说,Linux 系统的启动流程是这样的: 1. 开机之后,位于计算机主板 ROM 芯片上的 BIOS 被最先读取,在进行硬件和内存的校验以及 CPU 的自检没有异常后, BIO ...

  6. Linux学习总结(十八)几个简单的文本处理工具cut sort tr split

    1 命令cut 用来截取某一个字段格式 : cut -d '分隔符' [-cf] n, n为数字,表示第几段-d:后面跟分隔符,分割符要加单引号-c:后面接的是第几个字符-f:后面接的是第几段那么意思 ...

  7. 学习笔记:CentOS7学习之十八:Linux系统启动原理及故障排除

    目录 学习笔记:CentOS7学习之十八:Linux系统启动原理及故障排除 18.1 centos6系统启动过程及相关配置文件 18.1.1 centos6系统启动过程 18.1.2 centos6启 ...

  8. 鸟哥的linux私房菜——第十六章学习(程序管理与 SELinux 初探)

    第十六章.程序管理与 SE Linux 初探 在 Linux 系统当中:"触发任何一个事件时,系统都会将他定义成为一个程序,并且给予这个程序一个 ID ,称为 PID,同时依据启发这个程序的 ...

  9. 最简单的方法是使用标准的 Linux GUI 程序之一: i-nex 收集硬件信息,并且类似于 Windows 下流行的 CPU-Z 的显示。 HardInfo 显示硬件具体信息,甚至包括一组八个的流行的性能基准程序,你可以用它们评估你的系统性能。 KInfoCenter 和 Lshw 也能够显示硬件的详细信息,并且可以从许多软件仓库中获取。

    最简单的方法是使用标准的 Linux GUI 程序之一: i-nex 收集硬件信息,并且类似于 Windows 下流行的 CPU-Z 的显示. HardInfo 显示硬件具体信息,甚至包括一组八个的流 ...

随机推荐

  1. php实现设计模式之 访问者模式

    <?php /** * 访问者模式 * 封装某些作用于某种数据结构中各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作. * 行为类模式 */ /** 抽象访问者:抽象类或 ...

  2. socket.io,命名空间

    原文:http://www.cnblogs.com/xiezhengcai/p/3966263.html 命名空间 在api部分我们说io.connect('ws://103.31.201.154:5 ...

  3. 8、ASP.NET MVC入门到精通——View(视图)

    本系列目录:ASP.NET MVC4入门到精通系列目录汇总 View视图职责是向用户提供界面.负责根据提供的模型数据,生成准备提供给用户的格式界面. 支持多种视图引擎(Razor和ASPX视图引擎是官 ...

  4. 【再探backbone04】单页应用的基石-路由处理

    前言 首先发一点牢骚,互联网公司变化就是快,我去一个团队往往就一年时间该团队就得解散,这不,公司居然把无线团队解散了,我只能说,我那个去!!! 我去年还到处让人来呢,一个兴兴向荣的团队说没就没了啊!我 ...

  5. browserify压缩合并源码反编译

    最近在学习钉钉(一个协作应用)桌面应用的前端源码时候,发现其js源码是用browserify做模块开发.于是想还原其源码的原本的目录结构,学习它的目录分类以及业务划分. 前言 用过browserify ...

  6. Sql 获取日期区间

    获取制定日期区间 declare @d as date declare @d2 as date set @d = '2014-06-03' set @d2 ='2014-06-10' ),datead ...

  7. DVWA安装,ALMP环境搭建以及php版本转换

    前言 本文记录DVWA(Damn Vulberability Web App)在虚拟机中安装配置,包括ALMP环境的搭建和php版本的转换. 目录 2. ALMP环境搭建 3. php版本切换 一. ...

  8. iOS之加密的三种方法

    //需要导入   #import <CommonCrypto/CommonCryptor.h> ==============MD5加密============ NSString *str ...

  9. 【代码笔记】iOS-获取系统完成任务所需的后台时间

    一,代码. AppDelegate.h #import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplica ...

  10. 敏捷开发与jira之流程

    敏捷流程在Jira中的运用