diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 85f92bb36..59c0c47db 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,6 +4,10 @@ So, you want to hack on Open-IM-Server? Yay! First of all, thank you for considering contributing to our project! We appreciate your time and effort, and we value any contribution, whether it's reporting a bug, suggesting a new feature, or submitting a pull request. +![Hello OpenIM Image](assets/demo/hello-openim.png) + +> Use `make demo` start contributing fast. + This document provides guidelines and best practices to help you contribute effectively. ## 📇Topics diff --git a/assets/demo/hello-openim.png b/assets/demo/hello-openim.png new file mode 100644 index 000000000..2dd7e48ee Binary files /dev/null and b/assets/demo/hello-openim.png differ diff --git a/docs/contrib/util_go.md b/docs/contrib/util_go.md new file mode 100644 index 000000000..4126aa97c --- /dev/null +++ b/docs/contrib/util_go.md @@ -0,0 +1,8 @@ +# utils go + ++ [toold readme](https://github.com/OpenIMSDK/Open-IM-Server/tree/main/tools) + +about scripts fix: +``` +"${OPENIM-ROOT}/_output/bin/tools/${platform}/${lookfor}" +``` diff --git a/docs/contrib/util_makefile.md b/docs/contrib/util_makefile.md new file mode 100644 index 000000000..e0331f50e --- /dev/null +++ b/docs/contrib/util_makefile.md @@ -0,0 +1,90 @@ +# Open-IM-Server Development Tools Guide + +- [Open-IM-Server Development Tools Guide](#open-im-server-development-tools-guide) + - [Introduction](#introduction) + - [Getting Started](#getting-started) + - [Toolset Categories](#toolset-categories) + - [Installation Commands](#installation-commands) + - [Basic Installation](#basic-installation) + - [Individual Tool Installation](#individual-tool-installation) + - [Tool Verification](#tool-verification) + - [Detailed Tool Descriptions](#detailed-tool-descriptions) + - [Best Practices](#best-practices) + - [Conclusion](#conclusion) + + +## Introduction + +Open-IM-Server boasts a robust set of tools encapsulated within its Makefile system, designed to ease development, code formatting, and tool management. This guide aims to familiarize developers with the features and usage of the Makefile toolset provided within the Open-IM-Server project. + +## Getting Started + +Executing `make tools` ensures verification and installation of the default tools: + +- golangci-lint +- goimports +- addlicense +- deepcopy-gen +- conversion-gen +- ginkgo +- go-junit-report +- go-gitlint + +The installation path is situated at `/root/workspaces/openim/Open-IM-Server/_output/tools/`. + +## Toolset Categories + +The Makefile logically groups tools into different categories for better management: + +- **Development Tools**: `BUILD_TOOLS` +- **Code Analysis Tools**: `ANALYSIS_TOOLS` +- **Code Generation Tools**: `GENERATION_TOOLS` +- **Testing Tools**: `TEST_TOOLS` +- **Version Control Tools**: `VERSION_CONTROL_TOOLS` +- **Utility Tools**: `UTILITY_TOOLS` +- **Tencent Cloud Object Storage Tools**: `COS_TOOLS` + +## Installation Commands + +1. **golangci-lint**: high performance Go code linter with integration of multiple inspection tools. +2. **goimports**: Used to format Go source files and automatically add or remove imports. +3. **addlicense**: Adds a license header to the source file. +4. **deepcopy-gen and conversions-gen **: Generate deepcopy and conversion functionality. +5. **ginkgo**: Testing framework for Go. +6. **go-junit-report**: Converts Go test output to junit xml format. +7. **go-gitlint**: For checking git commit information. ... (And so on, list all the tools according to the `make tools.help` output above)... + + + +### Basic Installation + +- `tools.install`: Installs tools mentioned in the `BUILD_TOOLS` list. +- `tools.install-all`: Installs all tools from the `ALL_TOOLS` list. + +### Individual Tool Installation + +- `tools.install.%`: Installs a single tool in the `$GOBIN/` directory. +- `tools.install-all.%`: Parallelly installs an individual tool located in `./tools/*`. + +### Tool Verification + +- `tools.verify.%`: Checks if a specific tool is installed, and if not, installs it. + +## Detailed Tool Descriptions + +The following commands serve the purpose of installing particular development tools: + +- `install.golangci-lint`: Installs `golangci-lint`. +- `install.addlicense`: Installs `addlicense`. ... (and so on for every tool as mentioned in the provided Makefile source)... + +The commands primarily leverage Go's `install` operation, fetching and installing tools from their respective repositories. This method is especially convenient as it auto-handles dependencies and installation paths. For tools not written directly with Go (like `install.coscli`), other installation methods like wget or pip are employed. + +## Best Practices + +1. **Regular Updates**: To ensure tools are up-to-date, periodically run the `make tools` command. +2. **Individual Tools**: If only specific tools are required, employ the `make install.` command for individual installations. +3. **Verification**: Before code submissions, use the `make tools.verify.%` command to guarantee that all necessary tools are present and up-to-date. + +## Conclusion + +The Makefile provided by Open-IM-Server presents a centralized approach to manage and install all necessary tools during the development process. It ensures that all developers employ consistent tool versions, reducing potential issues due to version disparities. Whether you're a maintainer or a contributor to the Open-IM-Server project, understanding the workings of this Makefile will significantly enhance your developmental efficiency. diff --git a/docs/contrib/util_scripts.md b/docs/contrib/util_scripts.md new file mode 100644 index 000000000..0bf6f23e5 --- /dev/null +++ b/docs/contrib/util_scripts.md @@ -0,0 +1,248 @@ +# OpenIM Bash Utility Script + +This script offers a variety of utilities and helpers to enhance and simplify operations related to the OpenIM project. + +## Table of Contents + +- [OpenIM Bash Utility Script](#openim-bash-utility-script) + - [Table of Contents](#table-of-contents) + - [brief descriptions of each function](#brief-descriptions-of-each-function) + - [Introduction](#introduction) + - [Usage](#usage) + - [SSH Key Setup](#ssh-key-setup) + - [openim::util::ensure-gnu-sed](#openimutilensure-gnu-sed) + - [openim::util::ensure-gnu-date](#openimutilensure-gnu-date) + - [openim::util::check-file-in-alphabetical-order](#openimutilcheck-file-in-alphabetical-order) + - [openim::util::require-jq](#openimutilrequire-jq) + - [openim::util::md5](#openimutilmd5) + - [openim::util::read-array](#openimutilread-array) + - [Color Definitions](#color-definitions) + - [openim::util::desc and related functions](#openimutildesc-and-related-functions) + - [openim::util::onCtrlC](#openimutilonctrlc) + - [openim::util::list-to-string](#openimutillist-to-string) + - [openim::util::remove-space](#openimutilremove-space) + - [openim::util::gencpu](#openimutilgencpu) + - [openim::util::gen-os-arch](#openimutilgen-os-arch) + - [openim::util::download-file](#openimutildownload-file) + - [openim::util::get-public-ip](#openimutilget-public-ip) + - [openim::util::extract-tarball](#openimutilextract-tarball) + - [openim::util::check-port-open](#openimutilcheck-port-open) + - [openim::util::file-lines-count](#openimutilfile-lines-count) + + +## brief descriptions of each function + +**Englist:** +1. `openim::util::ensure-gnu-sed` - Determines if GNU version of `sed` exists on the system and sets its name. +2. `openim::util::ensure-gnu-date` - Determines if GNU version of `date` exists on the system and sets its name. +3. `openim::util::check-file-in-alphabetical-order` - Checks if a file is sorted in alphabetical order. +4. `openim::util::require-jq` - Checks if `jq` is installed. +5. `openim::util::md5` - Outputs the MD5 hash of a file. +6. `openim::util::read-array` - Reads content from standard input into an array. +7. `openim::util::desc` - Displays descriptive information. +8. `openim::util::run::prompt` - Displays a prompt. +9. `openim::util::run::maybe-first-prompt` - Possibly displays the first prompt based on whether it's started or not. +10. `openim::util::run` - Executes a command and captures its output. +11. `openim::util::run::relative` - Returns paths relative to the current script. +12. `openim::util::onCtrlC` - Performs an action when Ctrl+C is pressed. +13. `openim::util::list-to-string` - Converts a list into a string. +14. `openim::util::remove-space` - Removes spaces from a string. +15. `openim::util::gencpu` - Retrieves CPU information. +16. `openim::util::gen-os-arch` - Generates a repository directory based on the operating system and architecture. +17. `openim::util::download-file` - Downloads a file from a URL. +18. `openim::util::get-public-ip` - Retrieves the public IP address of the machine. +19. `openim::util::extract-tarball` - Extracts a tarball to a specified directory. +20. `openim::util::check-port-open` - Checks if a given port is open on the machine. +21. `openim::util::file-lines-count` - Counts the number of lines in a file. + + + +## Introduction + +This script is mainly used to validate whether the code is correctly formatted by `gofmt`. Apart from that, it offers utilities like setting up SSH keys, various wait conditions, host and platform detection, documentation generation, etc. + +## Usage + +### SSH Key Setup + +To set up an SSH key: + +```bash +#1. Write IPs in a file, one IP per line. Let's name it hosts-file. +#2. Modify the default username and password in the script. +hosts-file-path="path/to/your/hosts/file" +openim:util::setup_ssh_key_copy "$hosts-file-path" "root" "123" +``` + +## openim::util::ensure-gnu-sed + +Ensures the presence of the GNU version of the `sed` command. Different operating systems may have variations of the `sed` command, and this utility function is used to make sure the script uses the GNU version. If it finds the GNU `sed`, it sets the `SED` variable accordingly. If not found, it checks for `gsed`, which is usually the name of GNU `sed` on macOS. If neither is found, an error message is displayed. + + + +## openim::util::ensure-gnu-date + +Similar to the function for `sed`, this function ensures the script uses the GNU version of the `date` command. If it identifies the GNU `date`, it sets the `DATE` variable. On macOS, it looks for `gdate` as an alternative. In the absence of both, an error message is recommended. + + + +## openim::util::check-file-in-alphabetical-order + +This function checks if the contents of a given file are sorted in alphabetical order. If not, it provides a command suggestion for the user to sort the file correctly. + + + +## openim::util::require-jq + +Verifies the installation of `jq`, a popular command-line JSON parser. If it's not present, a prompt to install it is displayed. + + + +## openim::util::md5 + +A cross-platform function that computes the MD5 hash of its input. This function takes into account the differences in the `md5` command between macOS and Linux. + + + +## openim::util::read-array + +A function designed to read from stdin and populate an array, line by line. It's provided as an alternative to `mapfile -t` and is compatible with bash 3. + + + +## Color Definitions + +The script also defines a set of colors to enhance its console output. These include colors like red, yellow, green, blue, cyan, etc., which can be used for better user experience and clear logs. + + + +## openim::util::desc and related functions + +These functions seem to aid in building interactive demonstrations or tutorials in the terminal. They use the `pv` utility to control the display rate of the output, emulating typing. There's also functionality to handle user prompts and execute commands while capturing their output. + + + +## openim::util::onCtrlC + +Handles the `CTRL+C` command. It terminates background processes of the script when the user interrupts it using `CTRL+C`. + + + +## openim::util::list-to-string + +Transforms a list format (like `[10023, 2323, 3434]`) to a space-separated string (`10023 2323 3434`). Also removes unnecessary spaces and characters. + + + +## openim::util::remove-space + +Removes spaces from a given string. + + + +## openim::util::gencpu + +Fetches the number of CPUs using the `lscpu` command. + + + +## openim::util::gen-os-arch + +Identifies the operating system and architecture of the system running the script. This is useful to determine directories or binaries specific to that OS and architecture. + + + +## openim::util::download-file + +This function can be used to download a file from a URL. If `curl` is available, it uses `curl`. If not, it falls back to `wget`. + +```bash +function openim::util::download-file() { + local url="$1" + local dest="$2" + + if command -v curl &>/dev/null; then + curl -L "${url}" -o "${dest}" + elif command -v wget &>/dev/null; then + wget "${url}" -O "${dest}" + else + openim::log::error "Neither curl nor wget available. Cannot download file." + return 1 + fi +} +``` + + + +## openim::util::get-public-ip + +Fetches the public IP address of the machine. + +```bash +function openim::util::get-public-ip() { + if command -v curl &>/dev/null; then + curl -s https://ipinfo.io/ip + elif command -v wget &>/dev/null; then + wget -qO- https://ipinfo.io/ip + else + openim::log::error "Neither curl nor wget available. Cannot fetch public IP." + return 1 + fi +} +``` + + + +## openim::util::extract-tarball + +This function extracts a tarball to a specified directory. + +```bash +function openim::util::extract-tarball() { + local tarball="$1" + local dest="$2" + + mkdir -p "${dest}" + tar -xzf "${tarball}" -C "${dest}" +} +``` + + + +## openim::util::check-port-open + +Checks if a given port is open on the local machine. + +```bash +function openim::util::check-port-open() { + local port="$1" + if command -v nc &>/dev/null; then + echo -n > /dev/tcp/127.0.0.1/"${port}" 2>&1 + return $? + elif command -v telnet &>/dev/null; then + telnet 127.0.0.1 "${port}" 2>&1 | grep -q "Connected" + return $? + else + openim::log::error "Neither nc nor telnet available. Cannot check port." + return 1 + fi +} +``` + + + +## openim::util::file-lines-count + +Counts the number of lines in a file. + +```bash +function openim::util::file-lines-count() { + local file="$1" + if [[ -f "${file}" ]]; then + wc -l < "${file}" + else + openim::log::error "File does not exist: ${file}" + return 1 + fi +} +``` \ No newline at end of file diff --git a/scripts/advertise.sh b/scripts/advertise.sh index 9914e0710..2c9754fba 100755 --- a/scripts/advertise.sh +++ b/scripts/advertise.sh @@ -16,9 +16,9 @@ set -e set -o pipefail -. $(dirname ${BASH_SOURCE})/lib/color.sh +. $(dirname ${BASH_SOURCE})/lib/init.sh -trap 'openim::color::echo RED_PREFIX "Script interrupted."; exit 1' INT +openim::util::onCtrlC print_with_delay() { text="$1" @@ -89,7 +89,8 @@ O:::::::OOO:::::::O p:::::ppppp:::::::pe::::::::e n::::n n::::nII: print_with_delay "Open-IM-Server: Reinventing Instant Messaging" 0.01 print_progress 50 0.02 - print_with_delay "Open-IM-Server is not just a product; it's a revolution. It's about bringing the power of seamless, real-time messaging to your fingertips. And it's about joining a global community of developers, dedicated to pushing the boundaries of what's possible." 0.01 + print_with_delay "Open-IM-Server is not just a product; it's a revolution. It's about bringing the power of seamless," 0.01 + print_with_delay "real-time messaging to your fingertips. And it's about joining a global community of developers, dedicated to pushing the boundaries of what's possible." 0.01 print_progress 50 0.02 diff --git a/scripts/gendoc.sh b/scripts/gendoc.sh index d8ed279ce..27e45a90b 100755 --- a/scripts/gendoc.sh +++ b/scripts/gendoc.sh @@ -14,7 +14,7 @@ # limitations under the License. # Iterates over two directories: 'pkg' and 'internal/pkg'. -for top in pkg internal/pkg tools +for top in pkg internal/pkg do # Finds all subdirectories (including nested ones) under the current directory in the iteration ('pkg' or 'internal/pkg'). for d in $(find $top -type d) diff --git a/scripts/install_im_compose.sh b/scripts/install_im_compose.sh index 00191334a..732b0f27c 100755 --- a/scripts/install_im_compose.sh +++ b/scripts/install_im_compose.sh @@ -13,110 +13,62 @@ # limitations under the License. -#Include shell font styles and some basic information -SCRIPTS_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. +source "${OPENIM_ROOT}/scripts/lib/init.sh" +source "${OPENIM_ROOT}/scripts/install/environment.sh" -# docker-compose.yaml file name -docker_compose_file_name="docker-compose.yaml" - -trap 'onCtrlC' INT -function onCtrlC () { - #Capture CTRL+C, terminate the background process of the program when the script is terminated in the form of ctrl+c - kill -9 ${do_sth_pid} ${progress_pid} - echo - echo 'Ctrl+C is captured' - exit 1 -} +openim::util::onCtrlC -do_sth() { - #Main program to run - echo "++++++++++++++++++++++++" - sleep 5 - echo "++++++++++++++++++++++++" +docker_compose_file_name="docker-compose.yaml" - sleep 10 +# Load environment variables from .env file +load_env() { + source ${OPENIM_ROOT}/.env } -#Import environment variables -source .env +# Replace local IP with public IP in .env +replace_ip() { + if [ "$API_URL" == "http://127.0.0.1:10002/object/" ]; then + sed -i "s/127.0.0.1/${internet_ip}/" ${OPENIM_ROOT}/.env + fi -#Get the public IP address of the local machine -internet_ip=$(curl ifconfig.me -s) -echo -e "\033[1;34mCurrent public IP address: ${internet_ip}\033[0m\n" + if [ "$MINIO_ENDPOINT" == "http://127.0.0.1:10005" ]; then + sed -i "s/127.0.0.1/${internet_ip}/" ${OPENIM_ROOT}/.env + fi -#If MINIO_ENDPOINT is "http://127.0.0.1:10005", replace it with the current public IP address -if [[ $MINIO_ENDPOINT == "http://127.0.0.1:10005" ]]; then - sed -i "s/127.0.0.1/${internet_ip}/" .env -fi + openim::log::info "Your minio endpoint is ${MINIO_ENDPOINT}" +} -do_progress_bar() { - local duration=${1} - local max_progress=20 - local current_progress=0 +# Execute necessary scripts +execute_scripts() { + chmod +x ${OPENIM_ROOT}/scripts/*.sh + openim::log::info "Executing init_pwd.sh" + ${OPENIM_ROOT}/scripts/init_pwd.sh - while true; do - ((current_progress++)) - if [[ $current_progress -gt $max_progress ]]; then - break - fi - sleep "$duration" - echo "=====> Progress: [${current_progress}/${max_progress}]" - done + openim::log::info "Executing env_check.sh" + ${OPENIM_ROOT}/scripts/env_check.sh } -#Start Docker containers -start_docker_containers() { - if command -v docker-compose >/dev/null 2>&1; then - echo -e "\033[1;34mFound docker-compose command, starting docker containers...\033[0m\n" - docker-compose -f ${OPENIM_ROOT}/${docker_compose_file_name} up -d +# Start docker compose +start_docker_compose() { + openim::log::info "Checking if docker-compose command is available" + if command -v docker-compose &> /dev/null; then + docker-compose up -d else - if command -v docker >/dev/null 2>&1; then - echo -e "\033[1;34mFound docker command, starting docker containers...\033[0m\n" - docker compose -f ${OPENIM_ROOT}/${docker_compose_file_name} up -d - else - echo -e "\033[1;31mFailed to find docker-compose or docker command, please make sure they are installed and configured correctly.\033[0m" - return 1 - fi + docker compose up -d fi -} -#Execute scripts -setup_script() { - chmod +x ${SCRIPTS_ROOT}/*.sh - echo -e "\033[1;34m============>Executing init_pwd.sh script...\033[0m\n" - ${SCRIPTS_ROOT}/init_pwd.sh - echo -e "\033[1;34m============>Executing env_check.sh script...\033[0m\n" - ${SCRIPTS_ROOT}/env_check.sh + ${OPENIM_ROOT}/scripts/docker_check_service.sh } -setup_script & - -#Start Docker containers (timeout 10 seconds) -start_docker_containers - -docker_pid=$! -timeout 10s tail --pid=${docker_pid} -f /dev/null -docker_exit_code=$? - -if [ $docker_exit_code -eq 0 ]; then - echo -e "\033[1;32m============>Docker containers started successfully!\033[0m\n" -else - echo -e "\033[1;31m============>Failed to start Docker containers, please check the environment configuration and dependencies.\033[0m\n" - exit 1 -fi - -echo -e "\033[1;34m============>Executing docker_check_service.sh script...\033[0m\n" - -#View running Docker containers -echo -e "\033[1;34m============>Viewing running Docker containers...\033[0m\n" -echo "" -docker ps - -#Replace the progress bar section with the pv command -echo -e "\033[1;34m============>Starting progress bar...\033[0m\n" -do_progress_bar 0.5 | pv -l -s 20 > /dev/null -echo -e "\033[1;34m============>Progress bar completed.\033[0m\n" +main() { + load_env + openim::util::get_server_ip + replace_ip + execute_scripts + start_docker_compose + openim::log::success "Script executed successfully" +} -#Execute the main program -do_sth +# Run the main function +main \ No newline at end of file diff --git a/scripts/lib/util.sh b/scripts/lib/util.sh index 685e62d7f..b959d4e6e 100755 --- a/scripts/lib/util.sh +++ b/scripts/lib/util.sh @@ -128,7 +128,7 @@ openim::util::wait_for_url() { return 1 } -# Example: openim::util::wait_for_success 120 5 "imctl get nodes|grep localhost" +# Example: openim::util::wait_for_success 120 5 "openimctl get nodes|grep localhost" # arguments: wait time, sleep time, shell command # returns 0 if the shell command get output, 1 otherwise. openim::util::wait_for_success(){ @@ -277,7 +277,7 @@ openim::util::find-binary() { openim::util::find-binary-for-platform "$1" "$(openim::util::host_platform)" } -# Run all known doc generators (today gendocs and genman for imctl) +# Run all known doc generators (today gendocs and genman for openimctl) # $1 is the directory to put those generated documents openim::util::gen-docs() { local dest="$1" @@ -293,8 +293,8 @@ openim::util::gen-docs() { # least from k/k tree), remove it completely. openim::util::sourced_variable "${genfeddocs}" - mkdir -p "${dest}/docs/guide/en-US/cmd/imctl/" - "${gendocs}" "${dest}/docs/guide/en-US/cmd/imctl/" + mkdir -p "${dest}/docs/guide/en-US/cmd/openimctl/" + "${gendocs}" "${dest}/docs/guide/en-US/cmd/openimctl/" mkdir -p "${dest}/docs/guide/en-US/cmd/" "${genopenimdocs}" "${dest}/docs/guide/en-US/cmd/" "openim-api" @@ -310,7 +310,7 @@ openim::util::gen-docs() { "${genopenimdocs}" "${dest}/docs/guide/en-US/cmd/" "openim-rpc-msg" "${genopenimdocs}" "${dest}/docs/guide/en-US/cmd/" "openim-rpc-third" "${genopenimdocs}" "${dest}/docs/guide/en-US/cmd/" "openim-rpc-user" - "${genopenimdocs}" "${dest}/docs/guide/en-US/cmd/imctl" "imctl" + "${genopenimdocs}" "${dest}/docs/guide/en-US/cmd/openimctl" "openimctl" mkdir -p "${dest}/docs/man/man1/" "${genman}" "${dest}/docs/man/man1/" "openim-api" @@ -327,8 +327,8 @@ openim::util::gen-docs() { "${genman}" "${dest}/docs/man/man1/" "openim-rpc-third" "${genman}" "${dest}/docs/man/man1/" "openim-rpc-user" - mkdir -p "${dest}/docs/guide/en-US/yaml/imctl/" - "${genyaml}" "${dest}/docs/guide/en-US/yaml/imct/" + mkdir -p "${dest}/docs/guide/en-US/yaml/openimctl/" + "${genyaml}" "${dest}/docs/guide/en-US/yaml/openimctl/" # create the list of generated files pushd "${dest}" > /dev/null || return 1 @@ -553,7 +553,7 @@ EOF # flatten the openimconfig files to make them self contained username=$(whoami) ${sudo} /usr/bin/env bash -e < "/tmp/${client_id}.openimconfig" + $(openim::util::find-binary openimctl) --openimconfig="${dest_dir}/${client_id}.openimconfig" config view --minify --flatten > "/tmp/${client_id}.openimconfig" mv -f "/tmp/${client_id}.openimconfig" "${dest_dir}/${client_id}.openimconfig" chown ${username} "${dest_dir}/${client_id}.openimconfig" EOF @@ -896,6 +896,31 @@ function openim::util::run::relative() { done } +# This function retrieves the IP address of the current server. +# It primarily uses the `curl` command to fetch the public IP address from ifconfig.me. +# If curl or the service is not available, it falls back +# to the internal IP address provided by the hostname command. +function openim::util::get_server_ip() { + # Check if the 'curl' command is available + if command -v curl &> /dev/null; then + # Try to retrieve the public IP address using curl and ifconfig.me + IP=$(curl -s ifconfig.me) + + # Check if IP retrieval was successful + if [[ -z "$IP" ]]; then + # If not, get the internal IP address + IP=$(hostname -I | awk '{print $1}') + fi + else + # If curl is not available, get the internal IP address + IP=$(hostname -I | awk '{print $1}') + fi + + # Return the fetched IP address + echo "$IP" +} + + function openim::util::onCtrlC () { #Capture CTRL+C, terminate the background process of the program when the script is terminated in the form of ctrl+c kill -9 ${do_sth_pid} ${progress_pid}