add uninstall function

pull/70/head
Rikka 2 years ago committed by Rikka
parent 4d15b6153c
commit 0d7681bccb
No known key found for this signature in database
GPG Key ID: CD36B07FA9F7D2AA

@ -140,17 +140,19 @@ Star this repository if you find this useful, if you encounter problem create a
## Error handling ## Error handling
In case of error, if you retry immediately and it fails with this error - WayDroid no longer boots
```
==> Failed to resize image '/var/lib/waydroid/images/system.img' .. ! e2fsck 1.45.5 (07-Jan-2020)
/var/lib/waydroid/images/system.img is mounted.
e2fsck: Cannot continue, aborting.
```
You need to get the mounting point using `df | grep waydroid`. It will be something like `/dev/loopXXX`. Then, unmount it
``` ```
sudo umount /dev/loopXXX sudo waydroid upgrade -o
sudo systemctl restart waydroid-container.service
``` ```
And re-run the script. This will make `/var/lib/waydroid/waydroid_base.prop` return to original state, so libndk/libhoudini will be invalid. You need to modify `waydroid_base.prop` again.
Or use `sudo python3 main.py uninstall xxxxx` to remove what is causing the issue.
- Magisk installed: N/A
Check [waydroid-magisk](https://github.com/nitanmarcel/waydroid-magisk)
## Credits ## Credits
- [WayDroid](https://github.com/waydroid/waydroid) - [WayDroid](https://github.com/waydroid/waydroid)

@ -41,18 +41,10 @@ def install(*args):
def uninstall(*args): def uninstall(*args):
if "gapps" in args: if "gapps" in args:
Gapps().uninstall() Gapps().uninstall()
if "libndk" in args and "houdini" not in args: if "libndk" in args:
arch = helper.host()[0]
if arch == "x86_64":
Ndk().uninstall() Ndk().uninstall()
else: if "libhoudini" in args:
Logger.warn("libndk is not supported on your CPU")
if "libhoudini" in args and "ndk" not in args:
arch = helper.host()[0]
if arch == "x86_64":
Houdini().uninstall() Houdini().uninstall()
else:
Logger.warn("libhoudini is not supported on your CPU")
if "magisk" in args: if "magisk" in args:
Magisk().uninstall() Magisk().uninstall()
if "widevine" in args: if "widevine" in args:
@ -61,6 +53,8 @@ def uninstall(*args):
Smartdock().uninstall() Smartdock().uninstall()
if "nodataperm" in args: if "nodataperm" in args:
Nodataperm().uninstall() Nodataperm().uninstall()
if "microg" in args:
MicroG().uninstall()
def main(): def main():
about = """ about = """
@ -85,7 +79,7 @@ def main():
"type": str, "type": str,
"nargs": '+', "nargs": '+',
"metavar":"", "metavar":"",
"choices": ["gapps", "microg", "libndk","libhoudini","magisk", "smartdock","widevine", "nodataperm"], "choices": ["gapps", "microg", "libndk", "libhoudini", "magisk", "smartdock", "widevine", "nodataperm"],
} }
install_help = """ install_help = """

@ -27,6 +27,36 @@ class Gapps(General):
"setupwizarddefault-x86_64.tar.lz", "setupwizarddefault-x86_64.tar.lz",
"setupwizardtablet-x86_64.tar.lz" "setupwizardtablet-x86_64.tar.lz"
] ]
files = [
"etc/default-permissions/default-permissions.xml",
"etc/default-permissions/opengapps-permissions-q.xml",
"etc/permissions/com.google.android.maps.xml",
"etc/permissions/com.google.android.media.effects.xml",
"etc/permissions/privapp-permissions-google.xml",
"etc/permissions/split-permissions-google.xml",
"etc/preferred-apps/google.xml",
"etc/sysconfig/google.xml",
"etc/sysconfig/google_build.xml",
"etc/sysconfig/google_exclusives_enable.xml",
"etc/sysconfig/google-hiddenapi-package-whitelist.xml",
"framework/com.google.android.maps.jar",
"framework/com.google.android.media.effects.jar",
"priv-app/AndroidMigratePrebuilt",
"priv-app/GoogleExtServices",
"priv-app/GoogleRestore",
"priv-app/CarrierSetup",
"priv-app/GoogleExtShared",
"priv-app/GoogleServicesFramework",
"priv-app/ConfigUpdater",
"priv-app/GoogleFeedback",
"priv-app/Phonesky",
"priv-app/GoogleBackupTransport",
"priv-app/GoogleOneTimeInitializer",
"priv-app/PrebuiltGmsCore",
"priv-app/GoogleContactsSyncAdapter",
"priv-app/GooglePartnerSetup",
"product/overlay/PlayStoreOverlay.apk"
]
def copy(self): def copy(self):
if not os.path.exists(self.extract_to): if not os.path.exists(self.extract_to):

@ -1,6 +1,7 @@
import configparser import glob
import os import os
import re import re
import shutil
import zipfile import zipfile
import hashlib import hashlib
from tools import images from tools import images
@ -38,20 +39,47 @@ class General:
"md5 mismatches, redownloading now ....") "md5 mismatches, redownloading now ....")
loc_md5 = download_file(self.dl_link, self.download_loc) loc_md5 = download_file(self.dl_link, self.download_loc)
def remove(self):
for f in self.files:
file = os.path.join(self.copy_dir, self.partition, f)
if "*" in file:
for wildcard_file in glob.glob(file):
if os.path.isdir(wildcard_file):
shutil.rmtree(wildcard_file)
elif os.path.isfile(wildcard_file):
os.remove(wildcard_file)
else:
if os.path.isdir(file):
shutil.rmtree(file)
elif os.path.isfile(file):
os.remove(file)
def extract(self): def extract(self):
Logger.info("Extracting archive...") Logger.info("Extracting archive...")
with zipfile.ZipFile(self.download_loc) as z: with zipfile.ZipFile(self.download_loc) as z:
z.extractall(self.extract_to) z.extractall(self.extract_to)
def add_props(self): def add_props(self):
cfg = configparser.ConfigParser() with open(os.path.join("/var/lib/waydroid/waydroid_base.prop"), "r") as propfile:
cfg.read("/var/lib/waydroid/waydroid.cfg") prop_content = propfile.read()
for key in self.apply_props:
for key in self.apply_props.keys(): if key not in prop_content:
cfg.set('properties', key, self.apply_props[key]) prop_content = prop_content+"\n{key}={value}".format(key=key, value=self.apply_props[key])
else:
with open("/var/lib/waydroid/waydroid.cfg", "w") as f: p = re.compile(r"^{key}=.*$".format(key=key), re.M)
cfg.write(f) prop_content = re.sub(p, "{key}={value}".format(key=key, value=self.apply_props[key]), prop_content)
with open(os.path.join("/var/lib/waydroid/waydroid_base.prop"), "w") as propfile:
propfile.write(prop_content)
def remove_props(self):
with open(os.path.join("/var/lib/waydroid/waydroid_base.prop"), "r") as propfile:
prop_content = propfile.read()
for key in self.apply_props:
if key in prop_content:
p = re.compile(r"^{key}=.*(\n)*".format(key=key), re.M)
prop_content = re.sub(p, "", prop_content)
with open(os.path.join("/var/lib/waydroid/waydroid_base.prop"), "w") as propfile:
propfile.write(prop_content)
def mount(self): def mount(self):
img = os.path.join(images.get_image_dir(), self.partition+".img") img = os.path.join(images.get_image_dir(), self.partition+".img")
@ -103,6 +131,9 @@ class General:
def extra2(self): def extra2(self):
pass pass
def extra3(self):
pass
def install(self): def install(self):
if container.use_overlayfs(): if container.use_overlayfs():
self.download() self.download()
@ -131,4 +162,19 @@ class General:
Logger.info("Installation finished") Logger.info("Installation finished")
def uninstall(self): def uninstall(self):
pass if container.use_overlayfs():
self.remove()
if hasattr(self, "apply_props"):
self.remove_props()
self.extra3()
self.restart()
else:
self.stop()
self.mount()
self.remove()
if hasattr(self, "apply_props"):
self.remove_props()
self.extra3()
self.umount()
self.start()
Logger.info("Uninstallation finished")

@ -31,6 +31,18 @@ on property:ro.enable.native.bridge.exec=1
"ro.dalvik.vm.isa.arm": "x86", "ro.dalvik.vm.isa.arm": "x86",
"ro.dalvik.vm.isa.arm64": "x86_64" "ro.dalvik.vm.isa.arm64": "x86_64"
} }
files = [
"bin/arm",
"bin/arm64",
"bin/houdini",
"bin/houdini64",
"etc/binfmt_misc",
"etc/init/houdini.rc",
"lib/arm",
"lib/libhoudini.so",
"lib64/arm64",
"lib64/libhoudini.so"
]
def copy(self): def copy(self):
run(["chmod", "+x", self.extract_to, "-R"]) run(["chmod", "+x", self.extract_to, "-R"])

@ -3,7 +3,7 @@ import os
import shutil import shutil
import re import re
from stuffs.general import General from stuffs.general import General
from tools.helper import download_file, host, run from tools.helper import download_file, get_data_dir, host, run
from tools.logger import Logger from tools.logger import Logger
from tools import container from tools import container
@ -14,6 +14,7 @@ class Magisk(General):
extract_to = "/tmp/magisk_unpack" extract_to = "/tmp/magisk_unpack"
magisk_dir = os.path.join(partition, "etc", "init", "magisk") magisk_dir = os.path.join(partition, "etc", "init", "magisk")
machine = host() machine = host()
files = ["etc/init/magisk"]
oringinal_bootanim = """ oringinal_bootanim = """
service bootanim /system/bin/bootanimation service bootanim /system/bin/bootanimation
class core animation class core animation
@ -60,6 +61,13 @@ on property:init.svc.zygote=stopped
Logger.info("Downloading latest Magisk-Delta to {} now ...".format(self.download_loc)) Logger.info("Downloading latest Magisk-Delta to {} now ...".format(self.download_loc))
download_file(self.dl_link, self.download_loc) download_file(self.dl_link, self.download_loc)
# require additional setup
def setup(self):
Logger.info("Additional setup")
magisk_absolute_dir = os.path.join(self.copy_dir, self.magisk_dir)
data_dir = get_data_dir()
shutil.copytree(magisk_absolute_dir, os.path.join(data_dir, "adb", "magisk"), dirs_exist_ok=True)
def copy(self): def copy(self):
magisk_absolute_dir = os.path.join(self.copy_dir, self.magisk_dir) magisk_absolute_dir = os.path.join(self.copy_dir, self.magisk_dir)
if not os.path.exists(magisk_absolute_dir): if not os.path.exists(magisk_absolute_dir):
@ -79,6 +87,16 @@ on property:init.svc.zygote=stopped
shutil.copyfile(o_path, n_path) shutil.copyfile(o_path, n_path)
run(["chmod", "+x", n_path]) run(["chmod", "+x", n_path])
shutil.copyfile(self.download_loc, os.path.join(magisk_absolute_dir,"magisk.apk") ) shutil.copyfile(self.download_loc, os.path.join(magisk_absolute_dir,"magisk.apk") )
shutil.copytree(os.path.join(self.extract_to, "assets", "chromeos"), os.path.join(magisk_absolute_dir, "chromeos"), dirs_exist_ok=True)
assets_files = [
"addon.d.sh",
"boot_patch.sh",
"stub.apk",
"util_functions.sh"
]
for f in assets_files:
shutil.copyfile(os.path.join(self.extract_to, "assets", f), os.path.join(magisk_absolute_dir, f))
self.setup()
# Updating Magisk from Magisk manager will modify bootanim.rc, # Updating Magisk from Magisk manager will modify bootanim.rc,
# So it is necessary to backup the original bootanim.rc. # So it is necessary to backup the original bootanim.rc.
@ -94,16 +112,36 @@ on property:init.svc.zygote=stopped
def extra1(self): def extra1(self):
if container.use_overlayfs(): if container.use_overlayfs():
sys_overlay_rw = "/var/lib/waydroid/overlay_rw" sys_overlay_rw = "/var/lib/waydroid/overlay_rw"
old_bootanim_rc = os.path.join(sys_overlay_rw, "system","system", "etc", "init", "bootanim.rc") files = [
old_bootanim_rc_gz = os.path.join(sys_overlay_rw, "system","system", "etc", "init", "bootanim.rc.gz") "system/system/etc/init/bootanim.rc",
old_magisk = os.path.join(sys_overlay_rw, "system","system", "etc", "init", "magisk") "system/system/etc/init/bootanim.rc.gz",
"system/system/etc/init/magisk",
if os.path.exists(old_bootanim_rc): "system/system/addon.d/99-magisk.sh",
os.remove(old_bootanim_rc) "vendor/etc/selinux/precompiled_sepolicy"
if os.path.exists(old_bootanim_rc_gz): ]
os.remove(old_bootanim_rc_gz)
if os.path.exists(old_magisk): for f in files:
if os.path.isdir(old_magisk): file = os.path.join(sys_overlay_rw, f)
shutil.rmtree(old_magisk) if os.path.isdir(file):
shutil.rmtree(file)
elif os.path.isfile(file) or os.path.exists(file):
os.remove(file)
def extra3(self):
self.extra1()
data_dir = get_data_dir()
files = [
os.path.join(data_dir, "adb/magisk.db"),
os.path.join(data_dir, "adb/magisk")
]
for file in files:
if os.path.isdir(file):
shutil.rmtree(file)
elif os.path.isfile(file):
os.remove(file)
bootanim_path = os.path.join(self.copy_dir, self.partition, "etc", "init", "bootanim.rc")
if container.use_overlayfs():
os.remove(bootanim_path)
else: else:
os.remove(old_magisk) with open(bootanim_path, "w") as initfile:
initfile.write(self.oringinal_bootanim)

@ -28,6 +28,7 @@ class MicroG(General):
"com.android.vending-22.apk": "6815d191433ffcd8fa65923d5b0b0573", "com.android.vending-22.apk": "6815d191433ffcd8fa65923d5b0b0573",
"org.microg.gms.droidguard-14.apk": "4734b41c1a6bc34a541053ddde7a0f8e" "org.microg.gms.droidguard-14.apk": "4734b41c1a6bc34a541053ddde7a0f8e"
} }
priv_apps = ["com.google.android.gms", "com.android.vending"]
def skip_extract(self): def skip_extract(self):
return True return True
@ -59,12 +60,11 @@ class MicroG(General):
def copy(self): def copy(self):
Logger.info("Copying MicroG and other files") Logger.info("Copying MicroG and other files")
priv_apps = ["com.google.android.gms", "com.android.vending"]
for apk in {**self.fdroid_repo_apks, **self.microg_apks}.keys(): for apk in {**self.fdroid_repo_apks, **self.microg_apks}.keys():
splitor = "_" if apk in self.fdroid_repo_apks.keys() else "-" splitor = "_" if apk in self.fdroid_repo_apks.keys() else "-"
package = apk.split(splitor)[0] package = apk.split(splitor)[0]
download_dir = get_download_dir() download_dir = get_download_dir()
apk_dir = "app" if package not in priv_apps else "priv-app" apk_dir = "app" if package not in self.priv_apps else "priv-app"
if not os.path.exists(os.path.join(self.copy_dir, self.partition, apk_dir, package)): if not os.path.exists(os.path.join(self.copy_dir, self.partition, apk_dir, package)):
os.makedirs(os.path.join(self.copy_dir, self.partition, apk_dir, package)) os.makedirs(os.path.join(self.copy_dir, self.partition, apk_dir, package))
shutil.copyfile(os.path.join(download_dir, apk), shutil.copyfile(os.path.join(download_dir, apk),
@ -89,3 +89,17 @@ class MicroG(General):
Logger.info("Signature spoofing") Logger.info("Signature spoofing")
run("waydroid shell pm grant com.google.android.gms android.permission.FAKE_PACKAGE_SIGNATURE".split()) run("waydroid shell pm grant com.google.android.gms android.permission.FAKE_PACKAGE_SIGNATURE".split())
run("waydroid shell pm grant com.android.vending android.permission.FAKE_PACKAGE_SIGNATURE".split()) run("waydroid shell pm grant com.android.vending android.permission.FAKE_PACKAGE_SIGNATURE".split())
def remove(self):
system_dir = os.path.join(self.copy_dir, self.partition)
files = [key.split("_")[0] for key in self.fdroid_repo_apks.keys()]
files += [key.split("-")[0] for key in self.microg_apks.keys()]
for f in files:
if f in self.priv_apps:
file = os.path.join(system_dir, "priv-app", f)
else:
file = os.path.join(system_dir, "app", f)
if os.path.isdir(file):
shutil.rmtree(file)
elif os.path.isfile(file):
os.remove(file)

@ -1,4 +1,5 @@
from os import path, makedirs import glob
import os
import shutil import shutil
from stuffs.general import General from stuffs.general import General
from tools.helper import run from tools.helper import run
@ -6,10 +7,10 @@ from tools.logger import Logger
class Ndk(General): class Ndk(General):
partition = "system" partition = "system"
dl_link = "https://github.com/supremegamers/vendor_google_proprietary_ndk_translation-prebuilt/archive/181d9290a69309511185c4417ba3d890b3caaaa8.zip" dl_link = "https://www.dropbox.com/s/eaf4dj3novwiccp/libndk_translation_Module-c6077f3398172c64f55aad7aab0e55fad9110cf3.zip?dl=1"
dl_file_name = "libndktranslation.zip" dl_file_name = "libndktranslation.zip"
extract_to = "/tmp/libndkunpack" extract_to = "/tmp/libndkunpack"
act_md5 = "0beff55f312492f24d539569d84f5bfb" act_md5 = "4456fc1002dc78e544e8d9721bb24398"
apply_props = { apply_props = {
"ro.product.cpu.abilist": "x86_64,x86,armeabi-v7a,armeabi,arm64-v8a", "ro.product.cpu.abilist": "x86_64,x86,armeabi-v7a,armeabi,arm64-v8a",
"ro.product.cpu.abilist32": "x86,armeabi-v7a,armeabi", "ro.product.cpu.abilist32": "x86,armeabi-v7a,armeabi",
@ -31,23 +32,29 @@ on property:ro.enable.native.bridge.exec=1
copy /system/etc/binfmt_misc/arm64_exe /proc/sys/fs/binfmt_misc/register copy /system/etc/binfmt_misc/arm64_exe /proc/sys/fs/binfmt_misc/register
copy /system/etc/binfmt_misc/arm64_dyn /proc/sys/fs/binfmt_misc/register copy /system/etc/binfmt_misc/arm64_dyn /proc/sys/fs/binfmt_misc/register
""" """
files = [
"bin/arm",
"bin/arm64",
"bin/ndk_translation_program_runner_binfmt_misc",
"bin/ndk_translation_program_runner_binfmt_misc_arm64",
"etc/binfmt_misc",
"etc/ld.config.arm.txt",
"etc/ld.config.arm64.txt",
"etc/init/libndk.rc",
"lib/arm",
"lib64/arm64",
"lib/libndk*",
"lib64/libndk*"
]
def copy(self): def copy(self):
run(["chmod", "+x", self.extract_to, "-R"]) run(["chmod", "+x", self.extract_to, "-R"])
Logger.info("Copying libndk library files ...") Logger.info("Copying libndk library files ...")
archive_url, commit_sha = path.split(path.splitext(self.dl_link)[0]) shutil.copytree(os.path.join(self.extract_to, "libndk_translation_Module-c6077f3398172c64f55aad7aab0e55fad9110cf3", "system"), os.path.join(self.copy_dir, self.partition), dirs_exist_ok=True)
zipped_basepath, _ = path.split(archive_url)
prebuilts_sourcedir = path.join(
self.extract_to,
f"{path.basename(zipped_basepath)}-{commit_sha}",
"prebuilts")
shutil.copytree(
prebuilts_sourcedir,
path.join(self.copy_dir, self.partition),
dirs_exist_ok=True)
init_path = path.join(self.copy_dir, self.partition, "etc", "init", "libndk.rc") init_path = os.path.join(self.copy_dir, self.partition, "etc", "init", "libndk.rc")
if not path.isfile(init_path): if not os.path.isfile(init_path):
makedirs(path.dirname(init_path), exist_ok=True) os.makedirs(os.path.dirname(init_path), exist_ok=True)
with open(init_path, "w") as initfile: with open(init_path, "w") as initfile:
initfile.write(self.init_rc_component) initfile.write(self.init_rc_component)

@ -1,8 +1,10 @@
import gzip
import os import os
import shutil import shutil
from stuffs.general import General from stuffs.general import General
from tools.helper import run from tools.helper import run
from tools.logger import Logger from tools.logger import Logger
from tools import container
class Nodataperm(General): class Nodataperm(General):
dl_link = "https://github.com/ayasa520/hack_full_data_permission/archive/refs/heads/main.zip" dl_link = "https://github.com/ayasa520/hack_full_data_permission/archive/refs/heads/main.zip"
@ -10,11 +12,30 @@ class Nodataperm(General):
extract_to = "/tmp/nodataperm" extract_to = "/tmp/nodataperm"
act_md5 = "eafd7b0986f3edaebaf1dd89f19d49bf" act_md5 = "eafd7b0986f3edaebaf1dd89f19d49bf"
partition = "system" partition = "system"
files = [
"etc/nodataperm.sh",
"etc/init/nodataperm.rc",
"framework/services.jar"
]
def copy(self): def copy(self):
extract_path = os.path.join(self.extract_to, "hack_full_data_permission-main") extract_path = os.path.join(self.extract_to, "hack_full_data_permission-main")
if not container.use_overlayfs():
services_jar = os.path.join(self.copy_dir, self.partition, "framework", "services.jar")
gz_filename = services_jar+".gz"
with gzip.open(gz_filename,'wb') as f_gz:
with open(services_jar, "rb") as f:
f_gz.write(f.read())
os.chmod(os.path.join(extract_path, "framework", "services.jar"), 0o644) os.chmod(os.path.join(extract_path, "framework", "services.jar"), 0o644)
os.chmod(os.path.join(extract_path, "etc", "nodataperm.sh"), 0o755) os.chmod(os.path.join(extract_path, "etc", "nodataperm.sh"), 0o755)
os.chmod(os.path.join(extract_path, "etc", "init", "nodataperm.rc"), 0o755) os.chmod(os.path.join(extract_path, "etc", "init", "nodataperm.rc"), 0o755)
Logger.info("Copying widevine library files ...") Logger.info("Copying widevine library files ...")
shutil.copytree(extract_path, os.path.join(self.copy_dir, self.partition), dirs_exist_ok=True) shutil.copytree(extract_path, os.path.join(self.copy_dir, self.partition), dirs_exist_ok=True)
def extra3(self):
if not container.use_overlayfs():
services_jar = os.path.join(self.copy_dir, self.partition, "framework", "services.jar")
gz_filename = services_jar+".gz"
with gzip.GzipFile(gz_filename) as f_gz:
with open(services_jar, "wb") as f:
f.writelines(f_gz)

@ -12,6 +12,10 @@ class Smartdock(General):
dl_file_name = "smartdock.zip" dl_file_name = "smartdock.zip"
act_md5 = "ad0cc5e023ac6ee97e7b013b9b0defee" act_md5 = "ad0cc5e023ac6ee97e7b013b9b0defee"
apply_props = { "qemu.hw.mainkeys" : "1" } apply_props = { "qemu.hw.mainkeys" : "1" }
files = [
"etc/permissions/permissions_cu.axel.smartdock.xml",
"priv-app/SmartDock"
]
def copy(self): def copy(self):
if not os.path.exists(os.path.join(self.copy_dir, self.partition, "priv-app", "SmartDock")): if not os.path.exists(os.path.join(self.copy_dir, self.partition, "priv-app", "SmartDock")):

@ -11,6 +11,15 @@ class Widevine(General):
dl_file_name = "widevine.zip" dl_file_name = "widevine.zip"
extract_to = "/tmp/widevineunpack" extract_to = "/tmp/widevineunpack"
act_md5 = "a31f325453c5d239c21ecab8cfdbd878" act_md5 = "a31f325453c5d239c21ecab8cfdbd878"
files = [
"bin/hw/android.hardware.drm@1.3-service-lazy.widevine",
"bin/move_widevine_data.sh",
"etc/init/android.hardware.drm@1.3-service-lazy.widevine.rc",
"etc/vintf/manifest/manifest_android.hardware.drm@1.3-service.widevine.xml",
"lib/libwvhidl.so",
"lib/mediadrm",
"lib64/mediadrm"
]
def copy(self): def copy(self):
run(["chmod", "+x", self.extract_to, "-R"]) run(["chmod", "+x", self.extract_to, "-R"])

@ -19,6 +19,10 @@ def get_download_dir():
os.makedirs(download_loc) os.makedirs(download_loc)
return download_loc return download_loc
# not good
def get_data_dir():
return os.path.join('/', "home", os.environ.get("SUDO_USER", os.environ["USER"]), ".local", "share", "waydroid", "data")
def run(args, ignore=""): def run(args, ignore=""):
result = subprocess.run(args=args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) result = subprocess.run(args=args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# print(result.stdout.decode()) # print(result.stdout.decode())

Loading…
Cancel
Save