webui.sh 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. #!/usr/bin/env bash
  2. #################################################
  3. # Please do not make any changes to this file, #
  4. # change the variables in webui-user.sh instead #
  5. #################################################
  6. SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
  7. # If run from macOS, load defaults from webui-macos-env.sh
  8. if [[ "$OSTYPE" == "darwin"* ]]; then
  9. if [[ -f "$SCRIPT_DIR"/webui-macos-env.sh ]]
  10. then
  11. source "$SCRIPT_DIR"/webui-macos-env.sh
  12. fi
  13. fi
  14. # Read variables from webui-user.sh
  15. # shellcheck source=/dev/null
  16. if [[ -f "$SCRIPT_DIR"/webui-user.sh ]]
  17. then
  18. source "$SCRIPT_DIR"/webui-user.sh
  19. fi
  20. # If $venv_dir is "-", then disable venv support
  21. use_venv=1
  22. if [[ $venv_dir == "-" ]]; then
  23. use_venv=0
  24. fi
  25. # Set defaults
  26. # Install directory without trailing slash
  27. if [[ -z "${install_dir}" ]]
  28. then
  29. install_dir="$SCRIPT_DIR"
  30. fi
  31. # Name of the subdirectory (defaults to stable-diffusion-webui)
  32. if [[ -z "${clone_dir}" ]]
  33. then
  34. clone_dir="stable-diffusion-webui"
  35. fi
  36. # python3 executable
  37. if [[ -z "${python_cmd}" ]]
  38. then
  39. python_cmd="python3.10"
  40. fi
  41. if [[ ! -x "$(command -v "${python_cmd}")" ]]
  42. then
  43. python_cmd="python3"
  44. fi
  45. # git executable
  46. if [[ -z "${GIT}" ]]
  47. then
  48. export GIT="git"
  49. else
  50. export GIT_PYTHON_GIT_EXECUTABLE="${GIT}"
  51. fi
  52. # python3 venv without trailing slash (defaults to ${install_dir}/${clone_dir}/venv)
  53. if [[ -z "${venv_dir}" ]] && [[ $use_venv -eq 1 ]]
  54. then
  55. venv_dir="venv"
  56. fi
  57. if [[ -z "${LAUNCH_SCRIPT}" ]]
  58. then
  59. LAUNCH_SCRIPT="launch.py"
  60. fi
  61. # this script cannot be run as root by default
  62. can_run_as_root=0
  63. # read any command line flags to the webui.sh script
  64. while getopts "f" flag > /dev/null 2>&1
  65. do
  66. case ${flag} in
  67. f) can_run_as_root=1;;
  68. *) break;;
  69. esac
  70. done
  71. # Disable sentry logging
  72. export ERROR_REPORTING=FALSE
  73. # Do not reinstall existing pip packages on Debian/Ubuntu
  74. export PIP_IGNORE_INSTALLED=0
  75. # Pretty print
  76. delimiter="################################################################"
  77. printf "\n%s\n" "${delimiter}"
  78. printf "\e[1m\e[32mInstall script for stable-diffusion + Web UI\n"
  79. printf "\e[1m\e[34mTested on Debian 11 (Bullseye), Fedora 34+ and openSUSE Leap 15.4 or newer.\e[0m"
  80. printf "\n%s\n" "${delimiter}"
  81. # Do not run as root
  82. if [[ $(id -u) -eq 0 && can_run_as_root -eq 0 ]]
  83. then
  84. printf "\n%s\n" "${delimiter}"
  85. printf "\e[1m\e[31mERROR: This script must not be launched as root, aborting...\e[0m"
  86. printf "\n%s\n" "${delimiter}"
  87. exit 1
  88. else
  89. printf "\n%s\n" "${delimiter}"
  90. printf "Running on \e[1m\e[32m%s\e[0m user" "$(whoami)"
  91. printf "\n%s\n" "${delimiter}"
  92. fi
  93. if [[ $(getconf LONG_BIT) = 32 ]]
  94. then
  95. printf "\n%s\n" "${delimiter}"
  96. printf "\e[1m\e[31mERROR: Unsupported Running on a 32bit OS\e[0m"
  97. printf "\n%s\n" "${delimiter}"
  98. exit 1
  99. fi
  100. if [[ -d "$SCRIPT_DIR/.git" ]]
  101. then
  102. printf "\n%s\n" "${delimiter}"
  103. printf "Repo already cloned, using it as install directory"
  104. printf "\n%s\n" "${delimiter}"
  105. install_dir="${SCRIPT_DIR}/../"
  106. clone_dir="${SCRIPT_DIR##*/}"
  107. fi
  108. # Check prerequisites
  109. gpu_info=$(lspci 2>/dev/null | grep -E "VGA|Display")
  110. case "$gpu_info" in
  111. *"Navi 1"*)
  112. export HSA_OVERRIDE_GFX_VERSION=10.3.0
  113. if [[ -z "${TORCH_COMMAND}" ]]
  114. then
  115. pyv="$(${python_cmd} -c 'import sys; print(f"{sys.version_info[0]}.{sys.version_info[1]:02d}")')"
  116. # Using an old nightly compiled against rocm 5.2 for Navi1, see https://github.com/pytorch/pytorch/issues/106728#issuecomment-1749511711
  117. if [[ $pyv == "3.8" ]]
  118. then
  119. export TORCH_COMMAND="pip install https://download.pytorch.org/whl/nightly/rocm5.2/torch-2.0.0.dev20230209%2Brocm5.2-cp38-cp38-linux_x86_64.whl https://download.pytorch.org/whl/nightly/rocm5.2/torchvision-0.15.0.dev20230209%2Brocm5.2-cp38-cp38-linux_x86_64.whl"
  120. elif [[ $pyv == "3.9" ]]
  121. then
  122. export TORCH_COMMAND="pip install https://download.pytorch.org/whl/nightly/rocm5.2/torch-2.0.0.dev20230209%2Brocm5.2-cp39-cp39-linux_x86_64.whl https://download.pytorch.org/whl/nightly/rocm5.2/torchvision-0.15.0.dev20230209%2Brocm5.2-cp39-cp39-linux_x86_64.whl"
  123. elif [[ $pyv == "3.10" ]]
  124. then
  125. export TORCH_COMMAND="pip install https://download.pytorch.org/whl/nightly/rocm5.2/torch-2.0.0.dev20230209%2Brocm5.2-cp310-cp310-linux_x86_64.whl https://download.pytorch.org/whl/nightly/rocm5.2/torchvision-0.15.0.dev20230209%2Brocm5.2-cp310-cp310-linux_x86_64.whl"
  126. else
  127. printf "\e[1m\e[31mERROR: RX 5000 series GPUs python version must be between 3.8 and 3.10, aborting...\e[0m"
  128. exit 1
  129. fi
  130. fi
  131. ;;
  132. *"Navi 2"*) export HSA_OVERRIDE_GFX_VERSION=10.3.0
  133. ;;
  134. *"Navi 3"*) [[ -z "${TORCH_COMMAND}" ]] && \
  135. export TORCH_COMMAND="pip install torch torchvision --index-url https://download.pytorch.org/whl/nightly/rocm5.7"
  136. ;;
  137. *"Renoir"*) export HSA_OVERRIDE_GFX_VERSION=9.0.0
  138. printf "\n%s\n" "${delimiter}"
  139. printf "Experimental support for Renoir: make sure to have at least 4GB of VRAM and 10GB of RAM or enable cpu mode: --use-cpu all --no-half"
  140. printf "\n%s\n" "${delimiter}"
  141. ;;
  142. *)
  143. ;;
  144. esac
  145. if ! echo "$gpu_info" | grep -q "NVIDIA";
  146. then
  147. if echo "$gpu_info" | grep -q "AMD" && [[ -z "${TORCH_COMMAND}" ]]
  148. then
  149. export TORCH_COMMAND="pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/rocm5.7"
  150. elif npu-smi info 2>/dev/null
  151. then
  152. export TORCH_COMMAND="pip install torch==2.1.0 torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu; pip install torch_npu==2.1.0"
  153. fi
  154. fi
  155. for preq in "${GIT}" "${python_cmd}"
  156. do
  157. if ! hash "${preq}" &>/dev/null
  158. then
  159. printf "\n%s\n" "${delimiter}"
  160. printf "\e[1m\e[31mERROR: %s is not installed, aborting...\e[0m" "${preq}"
  161. printf "\n%s\n" "${delimiter}"
  162. exit 1
  163. fi
  164. done
  165. if [[ $use_venv -eq 1 ]] && ! "${python_cmd}" -c "import venv" &>/dev/null
  166. then
  167. printf "\n%s\n" "${delimiter}"
  168. printf "\e[1m\e[31mERROR: python3-venv is not installed, aborting...\e[0m"
  169. printf "\n%s\n" "${delimiter}"
  170. exit 1
  171. fi
  172. cd "${install_dir}"/ || { printf "\e[1m\e[31mERROR: Can't cd to %s/, aborting...\e[0m" "${install_dir}"; exit 1; }
  173. if [[ -d "${clone_dir}" ]]
  174. then
  175. cd "${clone_dir}"/ || { printf "\e[1m\e[31mERROR: Can't cd to %s/%s/, aborting...\e[0m" "${install_dir}" "${clone_dir}"; exit 1; }
  176. else
  177. printf "\n%s\n" "${delimiter}"
  178. printf "Clone stable-diffusion-webui"
  179. printf "\n%s\n" "${delimiter}"
  180. "${GIT}" clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git "${clone_dir}"
  181. cd "${clone_dir}"/ || { printf "\e[1m\e[31mERROR: Can't cd to %s/%s/, aborting...\e[0m" "${install_dir}" "${clone_dir}"; exit 1; }
  182. fi
  183. if [[ $use_venv -eq 1 ]] && [[ -z "${VIRTUAL_ENV}" ]];
  184. then
  185. printf "\n%s\n" "${delimiter}"
  186. printf "Create and activate python venv"
  187. printf "\n%s\n" "${delimiter}"
  188. cd "${install_dir}"/"${clone_dir}"/ || { printf "\e[1m\e[31mERROR: Can't cd to %s/%s/, aborting...\e[0m" "${install_dir}" "${clone_dir}"; exit 1; }
  189. if [[ ! -d "${venv_dir}" ]]
  190. then
  191. "${python_cmd}" -m venv "${venv_dir}"
  192. "${venv_dir}"/bin/python -m pip install --upgrade pip
  193. first_launch=1
  194. fi
  195. # shellcheck source=/dev/null
  196. if [[ -f "${venv_dir}"/bin/activate ]]
  197. then
  198. source "${venv_dir}"/bin/activate
  199. # ensure use of python from venv
  200. python_cmd="${venv_dir}"/bin/python
  201. else
  202. printf "\n%s\n" "${delimiter}"
  203. printf "\e[1m\e[31mERROR: Cannot activate python venv, aborting...\e[0m"
  204. printf "\n%s\n" "${delimiter}"
  205. exit 1
  206. fi
  207. else
  208. printf "\n%s\n" "${delimiter}"
  209. printf "python venv already activate or run without venv: ${VIRTUAL_ENV}"
  210. printf "\n%s\n" "${delimiter}"
  211. fi
  212. # Try using TCMalloc on Linux
  213. prepare_tcmalloc() {
  214. if [[ "${OSTYPE}" == "linux"* ]] && [[ -z "${NO_TCMALLOC}" ]] && [[ -z "${LD_PRELOAD}" ]]; then
  215. # check glibc version
  216. LIBC_VER=$(echo $(ldd --version | awk 'NR==1 {print $NF}') | grep -oP '\d+\.\d+')
  217. echo "glibc version is $LIBC_VER"
  218. libc_vernum=$(expr $LIBC_VER)
  219. # Since 2.34 libpthread is integrated into libc.so
  220. libc_v234=2.34
  221. # Define Tcmalloc Libs arrays
  222. TCMALLOC_LIBS=("libtcmalloc(_minimal|)\.so\.\d" "libtcmalloc\.so\.\d")
  223. # Traversal array
  224. for lib in "${TCMALLOC_LIBS[@]}"
  225. do
  226. # Determine which type of tcmalloc library the library supports
  227. TCMALLOC="$(PATH=/sbin:/usr/sbin:$PATH ldconfig -p | grep -P $lib | head -n 1)"
  228. TC_INFO=(${TCMALLOC//=>/})
  229. if [[ ! -z "${TC_INFO}" ]]; then
  230. echo "Check TCMalloc: ${TC_INFO}"
  231. # Determine if the library is linked to libpthread and resolve undefined symbol: pthread_key_create
  232. if [ $(echo "$libc_vernum < $libc_v234" | bc) -eq 1 ]; then
  233. # glibc < 2.34 pthread_key_create into libpthread.so. check linking libpthread.so...
  234. if ldd ${TC_INFO[2]} | grep -q 'libpthread'; then
  235. echo "$TC_INFO is linked with libpthread,execute LD_PRELOAD=${TC_INFO[2]}"
  236. # set fullpath LD_PRELOAD (To be on the safe side)
  237. export LD_PRELOAD="${TC_INFO[2]}"
  238. break
  239. else
  240. echo "$TC_INFO is not linked with libpthread will trigger undefined symbol: pthread_Key_create error"
  241. fi
  242. else
  243. # Version 2.34 of libc.so (glibc) includes the pthread library IN GLIBC. (USE ubuntu 22.04 and modern linux system and WSL)
  244. # libc.so(glibc) is linked with a library that works in ALMOST ALL Linux userlands. SO NO CHECK!
  245. echo "$TC_INFO is linked with libc.so,execute LD_PRELOAD=${TC_INFO[2]}"
  246. # set fullpath LD_PRELOAD (To be on the safe side)
  247. export LD_PRELOAD="${TC_INFO[2]}"
  248. break
  249. fi
  250. fi
  251. done
  252. if [[ -z "${LD_PRELOAD}" ]]; then
  253. printf "\e[1m\e[31mCannot locate TCMalloc. Do you have tcmalloc or google-perftool installed on your system? (improves CPU memory usage)\e[0m\n"
  254. fi
  255. fi
  256. }
  257. KEEP_GOING=1
  258. export SD_WEBUI_RESTART=tmp/restart
  259. while [[ "$KEEP_GOING" -eq "1" ]]; do
  260. if [[ ! -z "${ACCELERATE}" ]] && [ ${ACCELERATE}="True" ] && [ -x "$(command -v accelerate)" ]; then
  261. printf "\n%s\n" "${delimiter}"
  262. printf "Accelerating launch.py..."
  263. printf "\n%s\n" "${delimiter}"
  264. prepare_tcmalloc
  265. accelerate launch --num_cpu_threads_per_process=6 "${LAUNCH_SCRIPT}" "$@"
  266. else
  267. printf "\n%s\n" "${delimiter}"
  268. printf "Launching launch.py..."
  269. printf "\n%s\n" "${delimiter}"
  270. prepare_tcmalloc
  271. "${python_cmd}" -u "${LAUNCH_SCRIPT}" "$@"
  272. fi
  273. if [[ ! -f tmp/restart ]]; then
  274. KEEP_GOING=0
  275. fi
  276. done