【B - Networking】

最小生成树Prim算法实现

思路:

  • 最小生成树,点很少,边无界,Prim邻接矩阵

代码:

  • 16ms 708kB
//16ms		708kB


#include <iostream>
#include <cstring>
#include <queue>
#include <cstdio>
#include <algorithm>
#define INF 0x3f3f3f3f

using namespace std;

const int maxn = 55;

int P,R;
int ans;
int mp[maxn][maxn];
int dis[maxn];
int vis[maxn];
struct NODE{
	int id;
	int dis;
	friend bool operator > (NODE a,NODE b){
		return a.dis > b.dis;
	}
	NODE(int id,int dis) : id(id) , dis(dis) {} ;
};
priority_queue<NODE , vector<NODE> , greater<NODE> > Q;

void INIT(){
	ans = 0;
	memset(vis , 0 , sizeof(vis));
	memset(dis , INF , sizeof(dis));
	memset(mp , INF , sizeof(mp));
	return ;
}

void PRIM(){
	dis[1] = 0;
	Q.push(NODE(1,0));
	while(Q.size()){
		NODE cur = Q.top() ; Q.pop() ;
		int id = cur.id ;
		if(!vis[id]){
			vis[id] = true;
			ans += dis[id];
			for(int j=1;j<=P;j++)
				//只更新id的直连点(id的间连点的dis一定比id的直连点的dis大,可以以后再更新) 
				if(dis[j] > mp[id][j]){
					dis[j] = mp[id][j];
					Q.push(NODE(j , dis[j]));
				}
		} 
	}
	return ;
}

int main(){
	while(cin>>P && P){
		cin>>R;
		INIT();
		for(int i=1;i<=R;i++){
			int l,r,w;
			scanf("%d%d%d" , &l , &r , &w);
			mp[l][r] = mp[r][l] = min(mp[l][r] , w);
		}
		PRIM();
		cout<<ans<<endl;
	}
	return 0;
}
<think>我们面临的核心问题是:在已禁用sudo的计算机上(即无法使用sudo命令),如何执行需要特权的mysqld命令(--user=mysql --skip-grant-tables --skip-networking &)以重置MySQL 8.4.0的root密码。 分析: 1. 通常,mysqld需要以特定用户(如mysql)运行,并且需要绑定特权端口(3306),因此需要root权限。 2. 但sudo被禁用,意味着我们无法直接以root身份运行命令。 解决方案思路: 方案A:如果当前用户是root,则可以直接运行命令。 方案B:如果当前用户不是root,但具有运行mysqld的特殊权限(如通过setcap给mysqld设置能力),则可能无需sudo。 方案C:利用已有的MySQL服务管理方式(如systemctl)来设置环境变量,但需要当前用户有权限操作服务(通常也需要sudo)。 方案D:使用非特权端口启动MySQL,这样就不需要root权限。但是,MySQL默认使用3306(特权端口),我们可以修改端口为非特权端口(>1024)。然而,在密码重置过程中,我们通常希望阻止远程连接(使用--skip-networking),但使用非特权端口后,我们可以省略--skip-networking,因为非特权端口允许任意用户绑定,但为了安全,我们还是希望阻止网络连接,不过--skip-networking选项不需要特权。 然而,我们的目标命令中包含了--user=mysql,这要求我们能够切换用户(mysql),而切换用户通常需要sudo。因此,如果我们当前用户不是mysql,又不能使用sudo,那么无法以mysql用户身份启动。 因此,我们需要分情况考虑: 情况1:当前用户是root(虽然sudo被禁用,但我们可以已经是root用户) 这种情况下,我们可以直接运行命令: mysqld --user=mysql --skip-grant-tables --skip-networking & 情况2:当前用户是mysql(或者可以访问mysql用户的数据文件) 我们可以以当前用户(mysql)启动,无需切换用户: mysqld --skip-grant-tables --skip-networking & 情况3:当前用户既不是root也不是mysql,且无法使用sudo 这种情况下,通常无法完成操作,因为: a. 无法切换到mysql用户 b. 无法以root身份启动 但有一种可能:MySQL数据目录的权限允许当前用户读写(这种情况很少,因为MySQL数据目录通常只允许mysql用户访问)。如果数据目录权限允许,我们可以尝试以当前用户启动,但需要指定数据目录和socket等参数,并且要确保当前用户有权限启动。 然而,MySQL在启动时要求数据目录的拥有者必须是运行mysqld的用户。因此,如果我们当前用户不是mysql,而数据目录属于mysql,则启动会失败。 因此,我们必须以mysql用户运行mysqld。在无法使用sudo的情况下,我们只能: - 如果当前用户是root,则使用--user=mysql - 如果当前用户是mysql,则直接运行 - 否则,需要其他方式切换到mysql用户(例如,使用su命令,但su命令通常需要root权限或知道mysql用户的密码) 但题目中已禁用sudo,且我们忘记了root密码(但这里我们是要重置MySQL密码,所以系统root密码不一定忘记,但题目说禁用sudo,说明当前用户没有sudo权限,但不代表当前用户不是root)。 综上,我们假设当前用户可能是root,也可能是普通用户(无法提权)。 步骤: 1. 确认当前用户身份: 使用命令:`whoami` 或 `id -un` 2. 如果当前用户是root: 直接执行: mysqld --user=mysql --skip-grant-tables --skip-networking & 然后按照常规步骤重置密码。 3. 如果当前用户是mysql: 执行: mysqld --skip-grant-tables --skip-networking & 4. 如果当前用户既不是root也不是mysql: 我们需要尝试切换到mysql用户。但如果没有sudo,且不知道mysql用户的密码(因为mysql用户通常不允许直接登录),则无法切换。 替代方案:使用su切换到mysql用户(如果当前用户在mysql用户组且mysql用户允许登录?通常不允许)。所以,这几乎不可行。 另一种思路:修改MySQL数据目录的权限,使得当前用户可以运行mysqld(但存在安全风险,且可能破坏原有权限)。步骤如下: a. 停止正在运行的MySQL服务(如果有) 如果之前MySQL是作为服务运行的,我们需要停止它。但是由于没有sudo,我们可能无法通过systemctl停止服务。我们可以通过查找进程并杀死的方式: ps aux | grep mysqld kill -9 <mysqld进程号> 注意:确保没有其他MySQL实例在运行。 b. 更改MySQL数据目录的拥有者(需要root权限,但我们没有,所以此路不通) 因此,这种情况下,唯一的办法是联系系统管理员,或者使用root账号(如果知道系统root密码,可以直接登录root操作,但题目未提及)。 考虑到以上情况,我们重点解决当前用户是root或mysql的情况。 具体步骤(假设当前用户是root或mysql): 步骤1:停止正在运行的MySQL服务(避免端口冲突) 如果之前MySQL服务是通过系统服务运行的,我们需要停止它。但由于没有sudo,我们只能通过发送信号的方式停止。我们可以使用pkill(需要root权限)或查找进程并杀死。如果当前用户是root,可以: pkill mysqld 或者: killall mysqld 如果当前用户是mysql,则只能杀死自己拥有的进程: pkill -u mysql mysqld # 需要root权限?所以当前用户如果是mysql,则无法杀死其他mysql进程(如果多个进程) 因此,更安全的方法是先查看进程: ps aux | grep mysqld 然后根据进程号杀死: kill -9 <进程号> 注意:如果无法停止原有服务,则尝试启动新的mysqld实例会失败(因为端口占用或数据目录锁定)。 步骤2:启动MySQL无认证模式 根据当前用户身份: - 如果是root:mysqld --user=mysql --skip-grant-tables --skip-networking & - 如果是mysql:mysqld --skip-grant-tables --skip-networking & 注意:如果启动失败,检查错误日志(通常位于/var/log/mysql/error.log或数据目录下的hostname.err),根据错误调整。 步骤3:连接MySQL mysql -u root 步骤4:在MySQL中重置密码(注意MySQL 8.4.0的语法) FLUSH PRIVILEGES; ALTER USER 'root'@'localhost' IDENTIFIED BY ''; -- 先设为空 FLUSH PRIVILEGES; exit; 步骤5:关闭无认证模式的MySQL实例 使用命令查找进程ID并杀死: ps aux | grep mysqld kill -9 <进程ID> 步骤6:正常启动MySQL服务(如果有服务脚本,但无法用sudo,所以我们可以用普通用户启动?) 如果之前是系统服务,我们可能需要恢复服务启动。但如果没有sudo,我们只能以当前用户启动(作为普通进程)。建议恢复原服务启动方式(如果可能)。 另一种做法:以正常模式启动MySQL(使用当前用户,但指定数据目录等): mysqld --user=mysql & # 如果是root 或者 mysqld & # 如果是mysql用户 但这样启动的MySQL可能和系统服务启动的配置不同。因此,最好是恢复系统服务。 不过,我们重置密码后,应该停止当前手动启动的实例,然后尝试启动系统服务(但如果没有sudo,可能无法启动系统服务)。这是一个矛盾点:系统服务通常需要root启动。 所以,如果我们没有sudo,我们可能只能以当前用户启动MySQL作为长期运行?这显然不适合生产环境。 因此,重置密码后,我们应该按照原来的方式启动MySQL。如果原来是通过系统服务启动的,而我们没有sudo,那么可能需要系统管理员介入来启动服务(或者使用其他途径获得sudo权限)。 总结: 在没有sudo的情况下,重置MySQL密码是可行的,但前提是当前用户是root或者是mysql用户。重置完成后,如果MySQL原来是以系统服务运行的,则需要系统管理员(或有sudo权限的用户)来重启服务。 步骤细节: 1. 停止原有MySQL进程(如果运行): 查看进程:`ps aux | grep mysqld` 杀死进程:`kill -9 <进程ID>` (对于多个进程,需要全部杀死) 2. 启动无认证模式: 如果当前用户是root: 执行:`mysqld --user=mysql --skip-grant-tables --skip-networking &` 如果当前用户是mysql: 执行:`mysqld --skip-grant-tables --skip-networking &` 3. 连接MySQL: mysql -u root 4. 重置密码: FLUSH PRIVILEGES; ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewPassword'; -- 注意:MySQL 8.4.0可能要求强密码,但可以先设置一个简单的,后续再调整 FLUSH PRIVILEGES; exit; 5. 停止无认证模式MySQL: 同样,通过ps找到进程并杀死。 6. 重新启动MySQL: 如果能够使用系统服务,则通过系统服务启动(需要sudo,所以不能则跳过)。否则,尝试用当前用户启动正常模式的MySQL: - 如果是root用户:`mysqld --user=mysql &` (然后可以使用mysql -u root -p登录) - 如果是mysql用户:`mysqld &` 注意:这样启动的MySQL是作为前台进程运行的,如果退出终端可能会停止。如果需要后台运行,可以配合nohup或screen。 7. 后续:建议联系管理员恢复系统服务启动,并确保MySQL服务随系统启动。 安全警告: 在无认证模式下启动MySQL时,一定要使用--skip-networking,否则任何远程用户都可以无密码登录。操作完成后,立即恢复正常模式。 引用用户提供的引用: 引用[3]中提到文件权限问题:如果操作过程中出现权限问题,需要检查数据目录的文件权限。例如,如果文件所属组不正确,可能导致启动失败。在启动前确保数据目录及其文件属于运行mysqld的用户(即当前用户)。 因此,在启动前,我们可以检查数据目录的权限: ls -l /var/lib/mysql # 默认数据目录 如果当前用户是root,但数据目录属于mysql,那么在启动时使用--user=mysql是没问题的。 如果当前用户是普通用户(非root、非mysql),并且试图启动,那么数据目录必须属于该用户,否则会报错。 如果遇到权限问题,参考引用[3]的方法调整文件所属用户(但需要root权限)。 综上所述,在已禁用sudo的计算机上,重置MySQL密码的可行性取决于当前用户的身份。如果当前用户是root或mysql,则可以完成;否则,需要寻求其他途径。 下面给出完整的步骤指南: </think>### 在禁用 `sudo` 的计算机上重置 MySQL 8.4.0 密码的解决方案 #### 1. **确认 MySQL 数据目录权限** ```bash ls -ld /var/lib/mysql # 默认数据目录 ``` - 确保当前用户对数据目录有**读写权限**(如属主是当前用户)[^3] - 若权限不足,尝试获取文件所有权(需系统管理员协助): ```bash chown -R $USER:$USER /var/lib/mysql ``` #### 2. **手动停止 MySQL 服务** ```bash pkill -f mysqld # 强制终止所有 MySQL 进程 ps aux | grep mysqld # 确认无 MySQL 进程残留 ``` #### 3. **以当前用户启动无认证模式** ```bash mysqld --datadir=/var/lib/mysql \ --skip-grant-tables \ --skip-networking \ --user=$USER & # 关键:使用当前用户身份 ``` > **参数说明**: > - `--datadir`:指定 MySQL 数据目录路径 > - `--user=$USER`:以当前用户身份运行(替代 `--user=mysql`) > - `&`:后台运行进程 #### 4. **连接 MySQL 并重置密码** ```bash mysql -u root ``` ```sql FLUSH PRIVILEGES; -- 清空 root 密码(适配 MySQL 8.4 认证插件) ALTER USER 'root'@'localhost' IDENTIFIED BY ''; FLUSH PRIVILEGES; EXIT; ``` #### 5. **重启 MySQL 并设置新密码** ```bash pkill -f mysqld # 停止无认证实例 mysqld --user=$USER & # 正常启动 mysql -u root -p # 密码为空直接回车 ``` ```sql -- 设置强密码(示例) ALTER USER 'root'@'localhost' IDENTIFIED BY 'New@Password123!'; ``` --- ### **关键问题解决方案** 1. **文件权限错误** - 现象:`ib_buffer_pool` 等文件属主错误 [^3] - 修复: ```bash find /var/lib/mysql -user root -exec chown $USER:$USER {} \; ``` 2. **端口冲突处理** ```bash netstat -tlnp | grep 3306 # 查看端口占用 kill -9 <占用进程PID> # 强制终止冲突进程 ``` 3. **认证协议错误** ```sql ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '密码'; ``` --- ### **安全操作指南** 1. 操作前备份数据目录: `cp -R /var/lib/mysql /backup/mysql_data_$(date +%F)` 2. 完成后恢复文件权限: ```bash chown -R mysql:mysql /var/lib/mysql ``` 3. 检测日志异常: `tail -f /var/log/mysql/error.log` > **注意**:此方法仅适用于当前用户对 MySQL 文件有所有权的情况。若系统存在强制访问控制(如 SELinux),需额外配置安全上下文[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值