使用PXE启动无系统盘的客户机并运行Ubuntu系统

准备

机器说明
server安装pxe相关软件,nfs-kernel-server,ip=192.168.1.2
client1带有硬盘,使用iso安装ubuntu系统,并安装日常工作需要用到的软件,做好相应配置,安装nfs客户端:nfs-common
client2没有系统盘,其他硬件配置跟client1一致,测试用 ,ip=192.168.1.4

1、参考如下链接在server端部署pxe环境
https://blog.csdn.net/u010438035/article/details/128396790
2、参考如下链接在server端和client1端分别部署nfs服务端和客户端
https://blog.csdn.net/u010438035/article/details/128422999

在server端配置OS根目录

Create a directory to hold the OS files for the client

sudo mkdir /nfsroot
vi /etc/exports
/nfsroot             *(rw,no_root_squash,async,insecure)

# sync your exports

sudo exportfs -rv

在client1端克隆文件系统

mount.nfs4  -onolock 192.168.1.2:/nfsroot /mnt
cp -ax /. /mnt/.
cp -ax /dev/. /mnt/dev/.

在client1端制作vmlinuz和initrd.img

# Copy current kernel version to your home directory.
# uname -r will print your kernel version, and ~ is shorthand for your home directory.

sudo cp /boot/vmlinuz-`uname -r` ~

Create an initrd.img file
Change the BOOT flag to nfs in /etc/initramfs-tools/initramfs.conf

#
# BOOT: [ local | nfs ]
#
# local - Boot off of local media (harddrive, USB stick).
#
# nfs - Boot using an NFS drive as the root of the drive.
#

BOOT=nfs

Change the MODULES flag to netboot in /etc/initramfs-tools/initramfs.conf

#
# MODULES: [ most | netboot | dep | list ]
#
# most - Add all framebuffer, acpi, filesystem, and harddrive drivers.
#
# dep - Try and guess which modules to load.
#
# netboot - Add the base modules, network modules, but skip block devices.
#
# list - Only include modules from the 'additional modules' list
#

MODULES=netboot

NOTE: if you have anything in /etc/initramfs-tools/conf.d/driver-policy, this line will be ignored.

Check which modules you will need for your network adapters and put their names into /etc/initramfs-tools/modules (for example forcedeth , r8169 or tulip)
Run mkinitramfs

mkinitramfs -o ~/initrd.img-`uname -r`

把在client1端生成的复制到server端的如下图所示的目录中:

scp ~/vmlinuz-`uname -r` 192.168.1.2:/var/ftpd/boot/live-server/vmlinuz
scp ~/initrd.img-`uname -r` 192.168.1.2:/var/ftpd/boot/live-server/initrd

检查一下vmlinuz和initrd权限是否如下所示,否则修改一下:
在这里插入图片描述

在这里插入图片描述

在server端修改grub.cfg

内容如下:

menuentry "Try or Install Ubuntu Server" {

    set gfxpayload=keep

    linux  /boot/live-server/vmlinuz root=/dev/nfs ip=dhcp nfsroot=192.168.1.2:/nfsroot rw

    initrd /boot/live-server/initrd

}

在server端修改网卡配置

编辑/nfsroot/etc/netplan/00-installer-config.yaml
可设置为dhcp=true

在server端修改fstab

/nfsroot/etc/fstab contains the information the client will use to mount file systems on boot, edit it to ensure it looks something like this ('note no swap')

# /etc/fstab: static file system information.
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
proc            /proc           proc    defaults        0       0
/dev/nfs       /               nfs    defaults          1       1
none            /tmp            tmpfs   defaults        0       0
none            /var/run        tmpfs   defaults        0       0
none            /var/lock       tmpfs   defaults        0       0
none            /var/tmp        tmpfs   defaults        0       0

NOTE: if you have entries for other tmpfs that's fine to leave them in there

在server端修改/nfsroot/etc/kernel/postinst.d/zz-update-grub,禁用grub更新

#exec update-grub 注释这一行如下面所示:

cat /nfsroot/etc/kernel/postinst.d/zz-update-grub
#! /bin/sh
set -e

which update-grub >/dev/null 2>&1 || exit 0

if type systemd-detect-virt >/dev/null 2>&1 &&
   systemd-detect-virt --quiet --container; then
        exit 0
fi

set -- $DEB_MAINT_PARAMS
mode="${1#\'}"
mode="${mode%\'}"
case $0:$mode in
    # Only run on postinst configure and postrm remove, to avoid wasting
    # time by calling update-grub multiple times on upgrade and removal.
    # Also run if we have no DEB_MAINT_PARAMS, in order to work with old
    # kernel packages.
    */postinst.d/*:|*/postinst.d/*:configure|*/postrm.d/*:|*/postrm.d/*:remove)
        if [ -e /boot/grub/grub.cfg ]; then
        #       exec update-grub
        fi
        ;;
esac

exit 0

验证

设置client2从pxe启动,client2开机后会自动进入Ubuntu系统,系统和client1的一样。

参考
https://help.ubuntu.com/community/DisklessUbuntuHowto

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: PXE 无盘系统的代码如下:default menu.c32 prompt 0 timeout 300 ONTIMEOUT 0label 0 menu label ^Boot from local disk menu default localboot 0label 1 menu label ^Boot from PXE kernel pxelinux.0 append vga=normal initrd=initrd.imglabel 2 menu label ^Boot from network kernel tftp://192.168.1.1/vmlinuz append initrd=initrd.img ip=dhcp ### 回答2: PXElite是一个开源的PXE无盘系统,用于在网络上引导和管理无盘机器。下面是一个简化的PXElite代码示例,用于展示如何实现基本功能: ```python # 导入必要的模块 import socket import struct # 定义常量 TFTP_SERVER_IP = '192.168.0.1' TFTP_SERVER_PORT = 69 BOOT_FILE = 'pxelinux.0' # 创建UDP套接字 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 设置超时时间 sock.settimeout(5) # 发送TFTP读请求 def send_tftp_read_request(filename): # 构建请求数据包 request_packet = struct.pack('!H', 1) + filename.encode() + struct.pack('!B', 0) + b'octet' + struct.pack('!B', 0) # 发送请求数据包 sock.sendto(request_packet, (TFTP_SERVER_IP, TFTP_SERVER_PORT)) # 接收TFTP响应 def receive_tftp_response(): try: # 接收响应数据 response_packet, _ = sock.recvfrom(516) # 解析响应数据 opcode = struct.unpack('!H', response_packet[:2])[0] block_number = struct.unpack('!H', response_packet[2:4])[0] data = response_packet[4:] return (opcode, block_number, data) except socket.timeout: return None # 写入启动文件 def write_boot_file(data): with open(BOOT_FILE, 'ab') as f: f.write(data) # 启动PXE无盘系统 def pxe_boot(): send_tftp_read_request(BOOT_FILE) while True: response = receive_tftp_response() if response is not None: opcode, block_number, data = response if opcode == 3 and block_number == 1: write_boot_file(data) continue elif opcode == 3 and block_number > 1: write_boot_file(data) ack_packet = struct.pack('!HH', 4, block_number) sock.sendto(ack_packet, (TFTP_SERVER_IP, TFTP_SERVER_PORT)) continue elif opcode == 5: print('Error: {}'.format(data.decode())) break else: print('Timeout!') break # 启动PXE无盘系统 pxe_boot() ``` 以上代码实现了一个简单的PXE无盘系统,通过TFTP协议从指定的服务器上下载启动文件,并将其保存到本地。代码使用UDP套接字进行数据传输,发送TFTP读请求,接收TFTP响应,并将接收到的数据写入到启动文件中。代码中的`TFTP_SERVER_IP`和`TFTP_SERVER_PORT`变量需要根据实际情况进行适当修改。接收到的数据将写入到名为`pxelinux.0`的启动文件中。 ### 回答3: PX(Pre-eXecution Environment)是一种网络启动协议,它允许计算机通过网络引导而无需本地硬盘。PXE 无盘系统是基于 PXE 协议实现的操作系统,下面是一个简单的 PXE 无盘系统的示例代码: ```python import socket def pxe_boot(): # 创建UDP Socket sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 设置端口和 IP 地址 port = 67 ip = "0.0.0.0" # 绑定Socket到IP地址和端口 sock.bind((ip, port)) # 接收从 PXE 客户端发送的数据 data, addr = sock.recvfrom(1024) # 解析客户端发送的数据 packet = parse_packet(data) # 根据解析结果进行相应处理 if packet["message_type"] == "DHCPDISCOVER": # 进行 DHCP Discover 处理 offer_packet = create_dhcp_offer(packet["transaction_id"]) sock.sendto(offer_packet, addr) elif packet["message_type"] == "DHCPREQUEST": # 进行 DHCP Request 处理 ack_packet = create_dhcp_ack(packet["transaction_id"], packet["requested_ip"]) sock.sendto(ack_packet, addr) # 关闭 Socket 连接 sock.close() def parse_packet(data): # 解析 DHCP 数据包 packet = {} # 实现解析逻辑,将解析结果填充到 packet 字典中 return packet def create_dhcp_offer(transaction_id): # 创建 DHCP Offer 数据包 offer_packet = {} # 实现创建 Offer 数据包的逻辑,将构建的数据包填充到 offer_packet 字典中 return offer_packet def create_dhcp_ack(transaction_id, ip): # 创建 DHCP ACK 数据包 ack_packet = {} # 实现创建 ACK 数据包的逻辑,将构建的数据包填充到 ack_packet 字典中 return ack_packet if __name__ == '__main__': pxe_boot() ``` 这段代码实现了简单的 PXE 无盘系统功能,它包括创建 UDP Socket、绑定端口和 IP 地址、接收 PXE 客户端发送的数据、解析数据包内容以及根据解析结果生成相应的 DHCP Offer 或 DHCP ACK 数据包,并发送给 PXE 客户端。这样,就可以通过网络启动计算机并无需本地硬盘。当然,这只是一个简化的示例,实际的 PXE 无盘系统还需要根据具体需求进行更加复杂的逻辑和功能实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值