forked from ActivePeter/offline_installer_packer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsetup.py
211 lines (170 loc) · 6.35 KB
/
setup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
import subprocess
import os
import sys
import tempfile
import yaml
def create_dockerfile(temp_dir):
dockerfile_content = """
FROM ubuntu:18.04
USER root
# 更新软件包索引并安装必要的工具
RUN apt-get update && \\
apt-get install -y apt-utils python3 python3-pip wget
# 安装 Python 依赖
RUN pip3 install --upgrade pip
RUN apt-get update
RUN apt-get install -y apt-offline unzip
# 设置工作目录
WORKDIR /app
# 复制 Python 脚本和启动脚本
# COPY download_debs.py /app/download_debs.py
# COPY run.sh /app/run.sh
# 设置启动脚本为可执行
# RUN chmod +x /app/run.sh
# 指定默认命令
CMD ["/app/run.sh"]
"""
with open(os.path.join(temp_dir, 'Dockerfile'), 'w') as f:
f.write(dockerfile_content)
def create_run_script(temp_dir):
run_script_content = """#!/bin/bash
# 检查参数数量
if [ "$#" -lt 2 ]; then
echo "Usage: /app/run.sh <output_dir> <package1> <package2> ..."
exit 1
fi
# 更新软件包索引
apt-get update
# 调用 Python 脚本
python3 /app/mount_scripts/download_debs.py "$@"
"""
with open(os.path.join(temp_dir, 'run.sh'), 'w') as f:
f.write(run_script_content)
os.chmod(os.path.join(temp_dir, 'run.sh'), 0o755)
def create_container_script(temp_dir):
container_script_content = """#!/usr/bin/env python3
import subprocess
import os
import sys
def os_system(command):
print(f"Executing command: {command}")
result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
if result.returncode != 0:
print(f"Error executing command: {result.stderr}")
return False
return True
def get_dependencies(package_name):
result = subprocess.run(
['apt-cache', 'depends', '--recurse', '--no-recommends', '--no-suggests', '--no-conflicts', '--no-breaks', '--no-replaces', '--no-enhances', package_name],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True
)
if result.returncode != 0:
print(f"Error getting dependencies for {package_name}: {result.stderr}")
return []
dependencies = result.stdout.splitlines()
print(f"Get dependencies for {package_name}, output: {dependencies}")
dependencies = [dep.strip() for dep in dependencies if dep.strip().startswith('Depends:')]
print(f"dependencies1: {dependencies}")
dependencies = [dep.split()[1] for dep in dependencies]
print(f"dependencies2: {dependencies}")
# remove repeated packages
dependencies = list(set(dependencies))
dependencies = [dep for dep in dependencies if not dep.strip().startswith('<')]
return dependencies
def download_packages(packages, output_dir):
os_system("ls")
os.chdir(output_dir)
for package in packages:
subprocess.run(['apt', 'download', package], check=True)
for f in os.listdir(output_dir):
if f.endswith('.deb') and f.find("%")!=-1:
newfname=f.replace('%','')
print(f"rename {f} to {newfname}")
os_system(f"mv {f} {newfname}")
def generate_install_script(packages, output_dir):
with open(os.path.join(output_dir, 'install.sh'), 'w') as f:
f.write('#!/bin/bash\\n')
for package in packages:
f.write(f'dpkg -i {package}.deb\\n')
os.chmod(os.path.join(output_dir, 'install.sh'), 0o755)
def main():
print("Enter Container Script")
if len(sys.argv) < 3:
print("Usage: python3 download_debs.py <output_dir> <package1> <package2> ...")
sys.exit(1)
import os, pwd
os.setuid(0)
os.setgid(0)
output_dir = "/app/output"
os.chdir(output_dir)
packages = sys.argv[2:]
print("Packages to download:", packages)
# if not os.path.exists(output_dir):
try:
print(f"Output directory does not exist, creating... {output_dir}")
os.makedirs(output_dir)
except:
pass
# all_packages = set()
for package in packages:
os_system(f"mkdir -p {package}")
os_system(f"apt-offline set {package}.sig --install-packages {package}")
os_system(f"apt-offline get {package}.sig -d {package}")
os_system(f"ls {package}")
# dependencies = get_dependencies(package)
# print(f"Getting dependencies for {package} with {dependencies}")
# all_packages.update(dependencies)
# all_packages.add(package)
os_system("ls")
# all_packages = sorted(all_packages)
# download_packages(all_packages, output_dir)
# generate_install_script(all_packages, output_dir)
if __name__ == "__main__":
main()
"""
with open(os.path.join(temp_dir, 'download_debs.py'), 'w') as f:
f.write(container_script_content)
def build_and_run_docker(output_dir, packages):
with tempfile.TemporaryDirectory() as temp_dir:
# 创建 Dockerfile
create_dockerfile(temp_dir)
# 创建 run.sh
create_run_script(temp_dir)
# 创建容器中的 Python 脚本
create_container_script(temp_dir)
# 构建 Docker 镜像
image_tag = 'download-debs:18.04'
subprocess.run(['docker', 'build', '-t', image_tag, temp_dir], check=True)
# 运行 Docker 容器
print(f"bind output dir: {os.path.abspath(output_dir)} to /app/output")
command = ['docker', 'run',
'-v', f'{os.path.abspath(output_dir)}:/app/output',
'-v', f'{temp_dir}:/app/mount_scripts',
'--entrypoint=/app/mount_scripts/run.sh',
image_tag, '/app/output'] + packages
subprocess.run(command, check=True)
def deb_one_pack(packname,sub_packs):
# if len(sys.argv) < 3:
# print("Usage: python3 download_debs.py <package1> <package2> ...")
# sys.exit(1)
output_dir = "releases/"+packname
# packages = sys.argv[2:]
if not os.path.exists(output_dir):
os.makedirs(output_dir)
os.system(f"chmod 777 {output_dir}")
build_and_run_docker(output_dir, sub_packs)
def main():
os.system("docker login")
ymls=[f for f in os.listdir("./") if f.endswith(".yml")]
for yml in ymls:
with open(yml) as f:
conf=yaml.safe_load(f)
for key in conf:
if key=='apt':
deb_one_pack(yml.split(".yml")[0],conf['apt'])
else:
print("unsupported conf key: {key}")
if __name__ == "__main__":
main()