Sunday, October 20, 2013

Shell Scripting - Best Practices

Most programming languages have a set of "best practices" that should be followed when writing code in that language. However, I have not been able to find a comprehensive one for shell scripting so have decided to write my own based on my experience writing shell scripts over the years.

A note on portability: Since I mainly write shell scripts to run on systems which have Bash 4.2 installed, I don't need to worry about portability much, but you might need to! The list below is written with Bash 4.2 (and other modern shells) in mind. If you are writing a portable script, some points will not apply. Needless to say, you should perform sufficient testing after making any changes based on this list :-)

Here is my list of best practices for shell scripting (in no particular order):

  1. Use functions
  2. Document your functions
  3. Use shift to read function arguments
  4. Declare your variables
  5. Quote all parameter expansions
  6. Use arrays where appropriate
  7. Use "$@" to refer to all arguments
  8. Use uppercase variable names for environment variables only
  9. Prefer shell builtins over external programs
  10. Avoid unnecessary pipelines
  11. Avoid parsing ls
  12. Use globbing
  13. Use null delimited output where possible
  14. Don't use backticks
  15. Use process substitution instead of creating temporary files
  16. Use mktemp if you have to create temporary files
  17. Use [[ and (( for test conditions
  18. Use commands in test conditions instead of exit status
  19. Use set -e
  20. Write error messages to stderr

Each one of the points above is described in some detail below.

  1. Use functions

    Unless you're writing a very small script, use functions to modularise your code and make it more readable, reusable and maintainable. The template I use for all my scripts is shown below. As you can see, all code is written inside functions. The script starts off with a call to the main function.

    #!/bin/bash
    set -e
    
    usage() {
    }
    
    my_function() {
    }
    
    main() {
    }
    
    main "$@"
    
  2. Document your functions

    Add sufficient documentation to your functions to specify what they do and what arguments are required to invoke them. Here is an example:

    # Processes a file.
    # $1 - the name of the input file
    # $2 - the name of the output file
    process_file(){
    }
    
  3. Use shift to read function arguments

    Instead of using $1, $2 etc to pick up function arguments, use shift as shown below. This makes it easier to reorder arguments, if you change your mind later.

    # Processes a file.
    # $1 - the name of the input file
    # $2 - the name of the output file
    process_file(){
        local -r input_file="$1";  shift
        local -r output_file="$1"; shift
    }
    
  4. Declare your variables

    If your variable is an integer, declare it as such. Also, make all your variables readonly unless you intend to change their value later in your script. Use local for variables declared within functions. This helps convey your intent. If portability is a concern, use typeset instead of declare. Here are a few examples:

    declare -r -i port_number=8080
    declare -r -a my_array=( apple orange )
    
    my_function() {
        local -r name=apple
    }
    
  5. Quote all parameter expansions

    To prevent word-splitting and file globbing you must quote all variable expansions. In particular, you must do this if you are dealing with filenames that may contain whitespace (or other special characters). Consider this example:

    # create a file containing a space in its name
    touch "foo bar"
    
    declare -r my_file="foo bar"
    
    # try rm-ing the file without quoting the variable
    rm  $my_file
    # it fails because rm sees two arguments: "foo" and "bar"
    # rm: cannot remove `foo': No such file or directory
    # rm: cannot remove `bar': No such file or directory
    
    # need to quote the variable
    rm "$my_file"
    
    # file globbing example:
    mesg="my pattern is *.txt"
    echo $mesg
    # this is not quoted so *.txt will undergo expansion
    # will print "my pattern is foo.txt bar.txt"
    
    # need to quote it for correct output
    echo "$msg"
    
    

    It's good practice to quote all your variables. If you do need word-splitting, consider using an array instead. See the next point.

  6. Use arrays where appropriate

    Don't store a collection of elements in a string. Use an array instead. For example:

    # using a string to hold a collection
    declare -r hosts="host1 host2 host3"
    for host in $hosts  # not quoting $hosts here, since we want word splitting
    do
        echo "$host"
    done
    
    # use an array instead!
    declare -r -a host_array=( host1 host2 host3 )
    for host in "${host_array[@]}"
    do
        echo "$host"
    done
    
  7. Use "$@" to refer to all arguments

    Don't use $*. Refer to my previous post: Difference between $*, $@, "$*" and "$@". Here is an example:

    main() {
        # print each argument
        for i in "$@"
        do
            echo "$i"
        done
    }
    # pass all arguments to main
    main "$@"
    
  8. Use uppercase variable names for ENVIRONMENT variables only

    My personal preference is that all variables should be lowercase, except for environment variables. For example:

    declare -i port_number=8080
    
    # JAVA_HOME and CLASSPATH are environment variables
    "$JAVA_HOME"/bin/java -cp "$CLASSPATH" app.Main "$port_number"
    
  9. Prefer shell builtins over external programs

    The shell has the ability to manipulate strings and perform simple arithmetic so you don't need to invoke programs like cut and sed. Here are a few examples:

    declare -r my_file="/var/tmp/blah"
    
    # instead of dirname, use:
    declare -r file_dir="{my_file%/*}"
    
    # instead of basename, use:
    declare -r file_base="{my_file##*/}"
    
    # instead of sed 's/blah/hello', use:
    declare -r new_file="${my_file/blah/hello}"
    
    # instead of bc <<< "2+2", use:
    echo $(( 2+2 ))
    
    # instead of grepping a pattern in a string, use:
    [[ $line =~ .*blah$ ]]
    
    # instead of cut -d:, use an array:
    IFS=: read -a arr <<< "one:two:three"
    

    Note that an external program will perform better when operating on large files/input.

  10. Avoid unnecessary pipelines

    Pipelines add extra overhead to your script so try to keep your pipelines small. Common examples of useless pipelines are cat and echo, shown below:

    1. Avoid unnecessary cat

      If you are not familiar with the infamous Useless Use of Cat award, take a look here. The cat command should only be used for concatenating files, not for sending the output of a file to another command.

      # instead of
      cat file | command
      # use
      command < file
      
    2. Avoid unnecessary echo

      You should only use echo if you want to output some text to stdout, stderr, file etc. If you want to send text to another command, don't echo it through a pipe! Use a here-string instead. Note that here-strings are not portable (but most modern shells support them) so use a heredoc if you are writing a portable script. (See my earlier post: Useless Use of Echo.)

      # instead of
      echo text | command
      # use
      command <<< text
      
      # for portability, use a heredoc
      command << END
      text
      END
      
    3. Avoid unnecessary grep

      Piping from grep to awk or sed is unnecessary. Since both awk and sed can grep, you don't need the grep in your pipeline. (Check out my previous post: Useless Use of Grep.)

      # instead of
      grep pattern file | awk '{print $1}'
      # use
      awk '/pattern/{print $1}' file
      
      # instead of
      grep pattern file | sed 's/foo/bar/g'
      # use
      sed -n '/pattern/{s/foo/bar/p}' file
      
    4. Other unnecessary pipelines

      Here are a few other examples:

      # instead of
      command | sort | uniq
      # use
      command | sort -u
      
      # instead of
      command | grep pattern | wc -l
      # use
      command | grep -c pattern
      
  11. Avoid parsing ls

    The problem is that ls outputs filenames separated by newlines, so if you have a filename containing a newline character you won't be able to parse it correctly. It would be nice if ls could output null delimited filenames but, unfortunately, it can't. Instead of ls, use file globbing or an alternative command which outputs null terminated filenames, such as find -print0.

  12. Use globbing

    Globbing (or filename expansion) is the shell's way of generating a list of files matching a pattern. In bash, you can make globbing more powerful by enabling extended pattern matching operators using the extglob shell option. Also, enable nullglob so that you get an empty list if no matches are found. Globbing can be used instead of find in some cases and, once again, don't parse ls! Here are a couple of examples:

    
    shopt -s nullglob
    shopt -s extglob
    
    # get all files with a .yyyymmdd.txt suffix
    declare -a dated_files=( *.[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].txt )
    
    # get all non-zip files
    declare -a non_zip_files=( !(*.zip) )
    
    
  13. Use null delimited output where possible

    In order to correctly handle filenames containing whitespace and newline characters, you should use null delimited output, which results in each line being terminated by a NUL (\000) character instead of a newline. Most programs support this. For example, find -print0 outputs filenames followed by a null character and xargs -0 reads arguments separated by null characters.

    # instead of
    find . -type f -mtime +5 | xargs rm -f
    # use
    find . -type f -mtime +5 -print0 | xargs -0 rm -f
    
    # looping over files
    find . -type f -print0 | while IFS= read -r -d $'\0' filename; do
        echo "$filename"
    done
    
  14. Don't use backticks

    Use $(command) instead of `command` because it is easier to nest multiple commands and makes your code more readable. Here is a simple example:

    # ugly escaping required when using nested backticks
    a=`command1 \`command2\``
    
    # $(...) is cleaner
    b=$(command1 $(command2))
    
  15. Use process substitution instead of creating temporary files

    In most cases, if a command takes a file as an input, the file can be replaced by the output of another command using process substitution: <(command). This saves you from having to write out a temp file, passing that temp file to the command and finally deleting the temp file. This is shown below:

    # using temp files
    command1 > file1
    command2 > file2
    diff file1 file2
    rm file1 file2
    
    # using process substitution
    diff <(command1) <(command2)
    
  16. Use mktemp if you have to create temporary files

    Try to avoid creating temporary files. If you must, use mktemp to create a temporary directory and then write your files to it. Make sure you remove the directory after you are done.

    # set up a trap to delete the temp dir when the script exits
    unset temp_dir
    trap '[[ -d "$temp_dir" ]] && rm -rf "$temp_dir"' EXIT
    
    # create the temp dir
    declare -r temp_dir=$(mktemp -dt myapp.XXXXXX)
    
    # write to the temp dir
    command > "$temp_dir"/foo
    
  17. Use [[ and (( for test conditions

    Prefer [[ ... ]] over [ ... ] because it is safer and provides a richer set of features. Use (( ... )) for arithmetic conditions because it allows you to perform comparisons using familiar mathematical operators such as < and > instead of -lt and -gt. Note that if you desire portability, you have to stick to the old-fashioned [ ... ]. Here are a few examples:

    [[ $foo == "foo" ]] && echo "match"  # don't need to quote variable inside [[
    [[ $foo == "a" && $bar == "a" ]] && echo "match"
    
    declare -i num=5
    (( num < 10 )) && echo "match"       # don't need the $ on $num in ((
    
  18. Use commands in test conditions instead of exit status

    If you want to check whether a command succeeded before doing something, use the command directly in the condition of your if-statement instead of checking the command's exit status.

    
    # don't use exit status
    grep -q pattern file
    if (( $? == 0 ))
    then
        echo "pattern was found"
    fi
    
    # use the command as the condition
    if grep -q pattern file
    then
        echo "pattern was found"
    fi
    
  19. Use set -e

    Put this at the top of your script. This tells the shell to exit the script as soon as any statement returns a non-zero exit code.

  20. Write error messages to stderr

    Error messages belong on stderr not stdout.

    echo "An error message" >&2
    

If you have any other suggestions for my list, please share them in the comments section below!

60 comments:

  1. Your link to Difference between $*, $@, "$*" and "$@" points to the wrong place ;-)
    Next stop: a Sonar quality profile for shell scripts?

    ReplyDelete
  2. Well spotted, Gavin! I have fixed the link now. Thanks for reading :-)

    ReplyDelete
  3. Anonymous3:55 PM

    It's easier to port a shell, than a shell script, my shell-veteran friend likes to say. There's more to that then just a grain of truth. Other than that, I found myself quite in agreement!

    ReplyDelete
  4. You gathered a lot of useful recommendations that could be useful to *many* shell programmers! Maybe you could identify “bashisms” in your text, I noted 13 and 17. I am currently having a lot of trouble with bugs in Bash pledging its job management – Bash regularly core dumps!

    I just wrote a short text about a common error of shell beginners, consisting in implementing complex treatments in the shell, while these should be delegated to filters. I would love to read your comments on this text! http://unix-workstation.blogspot.de/2015/04/delegating-complex-treatments-to.html

    ReplyDelete

  5. Thank you so much for this nice information. Hope so many people will get aware of this and useful as well.
    DevOps Training
    DevOps Online Training
    DevOps Training in Ameerpet

    ReplyDelete
  6. Binance exchange is known worldwide for its popularity and despite all the excellent features, there are endless errors such as login , sign up, password issues which are faced by users on regular basis. If you don’t know how to deal with such troubles and looking for assistance, you can always call on Binance customer care number which is active and working around the clock so that users can deal with all queries on time and provide the best solutions from the experts. Reach the team members whenever you need help to deal with all queries. Binance Support Phone Number

    ReplyDelete
  7. This particular is usually apparently essential and moreover outstanding truth along with for sure fair-minded and moreover admittedly useful My business is looking to find in advance designed for this specific useful stuffs… Learn More

    ReplyDelete
  8. This article gives the light in which we can observe the reality. This is very nice one and gives indepth information. Thanks for this nice article. What to Do if Your Dog has an Ear Infection

    ReplyDelete
  9. Superbly written article, if only all bloggers offered the same content as you, the internet would be a far better place.. Read More

    ReplyDelete
  10. We have sell some products of different custom boxes.it is very useful and very low price please visits this site thanks and please share this post with your friends. Click Here

    ReplyDelete
  11. Thanks for posting this info. I just want to let you know that I just check out your site and I find it very interesting and informative. I can't wait to read lots of your posts. Best Cat Food for Weight Loss

    ReplyDelete
  12. Freelance maintenance technicians also benefit from establishing relationships with multiple clients. Working as a freelancer, you’ll gain employment experience with a variety of businesses, boosting your overall skill set and providing you with more work opportunities in the future.

    maintenance technician

    ReplyDelete
  13. KUBET được cộng đồng cá cược đánh giá là nhà cái số 1 Châu Á trong năm 2019 hiện tại. Với nhiều trò chơi hấp dẫn, tỷ lệ cược cực cao, trải nghiệm mượt mà mang tới cơ hội kiếm tiền cho anh em. KUBET.IO là trang web cung cấp link đăng ký, đăng nhập KU BET - KU CASINO chính thức, hướng dẫn hội viên tham gia các trò cá cược trên nhà cái, cũng như cách nạp tiền, rút tiền.



    Từ khóa: #ku, #kubet, #kucasino, #kubetio, #ku777, #ku888, #ku999, #casino, #thienhabet, #kubetcasino



    Mạng xã hội KUBET chính thức:


    https://infogram.com/dang-ky-kubet-cach-tao-lap-tai-khoan-ku-bet-don-gian-1h8j4xglr0od6mv

    https://trello.com/kubet

    https://block-x.co/dang-ky-kubet/

    https://www.youtube.com/channel/UCyPQbqZIZKV60Q7njSmKe3A


    https://www.surveymonkey.com/r/S5X7VBD


    ReplyDelete
  14. KUBET được cộng đồng cá cược đánh giá là nhà cái số 1 Châu Á trong năm 2019 hiện tại. Với nhiều trò chơi hấp dẫn, tỷ lệ cược cực cao, trải nghiệm mượt mà mang tới cơ hội kiếm tiền cho anh em. KUBET.IO là trang web cung cấp link đăng ký, đăng nhập KU BET - KU CASINO chính thức, hướng dẫn hội viên tham gia các trò cá cược trên nhà cái, cũng như cách nạp tiền, rút tiền.



    Từ khóa: #ku, #kubet, #kucasino, #kubetio, #ku777, #ku888, #ku999, #casino, #thienhabet, #kubetcasino



    Mạng xã hội KUBET chính thức:



    https://www.zenysro.cz/blogy/vztahy-a-partnerstvi/kubet-co-th-c-s-uy-tin-b-t-mi-t-i-ku-casino-kubet-io


    https://muckrack.com/kubet

    https://band.us/@kubetku777

    http://scholar.google.com/citations?user=mgWAXIsAAAAJ&hl=vi

    https://www.internship.edu.vn/companies/blogkubet-kubet-ku-casino-kubet-co/


    ReplyDelete
  15. Taxitaithanhhung.vn - công ty cung cấp giải pháp chuyển nhà trọn gói tại Hà Nội. Với mong muốn mang đến cho quý khách hàng dịch vụ vận chuyển nhà tại Hà Nội tốt nhất. Đội ngũ nhân viên chuyển nhà trọn gói Thành Hưng chuyên nghiệp, hệ thống xe tải với số lượng lớn, chúng tôi tự tin cam kết mang đến cho quý khách hàng 1 dịch vụ tốt nhất!

    Từ khóa chuyển nhà Hà Nội - công ty cung cấp dịch vụ chuyển nhà Thành Hưng:

    #chuyennhahanoi #chuyennhataihanoi #dichvuchuyennhahanoi #dichvuchuyennhataihanoi #dichvuchuyennhathanhhung #chuyennhatrongoithanhhung #chuyennhatrongoihanoi #chuyennhatrongoitaihanoi #donnhathanhhung #donnhatrongoihanoi #chuyennhagiarehanoi #dichvuchuyennhagiarehanoi

    https://tuoitre.vn/chuyen-nha-thanh-hung-20-nam-dong-hanh-va-phat-trien-thuong-hieu-20200422112222106.htm

    https://vnexpress.net/20-nam-taxi-tai-thanh-hung-phuc-vu-khach-hang-4075831.html

    https://dantri.com.vn/kinh-doanh/dich-vu-chuyen-nha-tron-goi-thanh-hung-20200319160451993.htm

    https://filmfreeway.com/chuyennhatrongoithanhhung

    https://medium.com/@vantaitthanhhung/dich-vu-chuyen-nha-thanh-hung-tai-ha-noi-9ddbff5cda4

    ReplyDelete

  16. There could be cases of files deletion or new files appearing. Though this symptom is basically because of virus infection, it may be attributed as a symptom for runtime error, as virus infection is among the causes for runtime error.
    Visit:
    https://www.dialsupportnumber.com/quickbooks-online-banking-error-9999

    ReplyDelete
  17. KuCasino.Email - Đại lý KUBET - KU CASINO chính thức, nhiều ưu đãi. Khuyến mãi cực lớn, tặng 588K cho hội viên đăng ký, nạp tiền lần đầu.


    Xem thêm: #ku, #kucasino, #kubet, #kucasinoemail, #casino

    http://uid.me/kucasinoemail

    https://about.me/kucasinoemail

    https://www.reddit.com/user/kucasinoemail

    https://mastodon.cloud/@kucasinoemail

    https://ko-fi.com/kucasinoemail


    Webste: KuCasino.Email

    ReplyDelete
  18. Chuyennhasgthanhhung.com - dịch vụ chuyển nhà trọn gói Hà Nội - chuyển nhà tại Hà Nội - chuyển nhà trọn gói Thành Hưng. Công ty cung cấp gói giải pháp chuyển nhà số 1 Việt Nam, liên hệ ngay với Thành Hưng để được báo giá nhanh nhất và chính xác nhất.

    Từ khóa chuyển nhà Hà Nội - công ty cung cấp dịch vụ chuyển nhà Thành Hưng:
    #chuyennhasgthanhhung #chuyennhasgthanhhung.com #chuyennhahanoi #chuyennhataihanoi #dichvuchuyennhahanoi #dichvuchuyennhataihanoi #dichvuchuyennhathanhhung #chuyennhatrongoithanhhung #chuyennhatrongoihanoi #chuyennhatrongoitaihanoi #donnhathanhhung #donnhatrongoihanoi #chuyennhagiarehanoi #dichvuchuyennhagiarehanoi


    Hệ thống social chuyển nhà Thành Hưng:

    https://sites.google.com/view/vantaithanhhung300

    https://www.24h.com.vn/thi-truong-24h/thanh-hung-dich-vu-chuyen-nha-chuyen-van-phong-tron-goi-c341a1104928.html

    https://www.zenysro.cz/blogy/napady-a-tvoreni/d-ch-v-chuy-n-nh-tr-n-goi-th-nh-h-ng-uy-tin-t-i-h-n-i

    https://issuu.com/vantaithanhhung300

    https://ello.co/vantaithanhhung


    ReplyDelete
  19. Taxitaithanhhung.vn - công ty cung cấp giải pháp chuyển nhà trọn gói tại Hà Nội. Với mong muốn mang đến cho quý khách hàng dịch vụ vận chuyển nhà tại Hà Nội tốt nhất. Đội ngũ nhân viên chuyển nhà trọn gói Thành Hưng chuyên nghiệp, hệ thống xe tải với số lượng lớn, chúng tôi tự tin cam kết mang đến cho quý khách hàng 1 dịch vụ tốt nhất!

    Từ khóa chuyển nhà Hà Nội - công ty cung cấp dịch vụ chuyển nhà Thành Hưng:

    #chuyennhahanoi #chuyennhataihanoi #dichvuchuyennhahanoi #dichvuchuyennhataihanoi #dichvuchuyennhathanhhung #chuyennhatrongoithanhhung #chuyennhatrongoihanoi #chuyennhatrongoitaihanoi #donnhathanhhung #donnhatrongoihanoi #chuyennhagiarehanoi #dichvuchuyennhagiarehanoi

    https://refind.com/chuyennhathanhhung

    https://muckrack.com/chuyennha-thanhhung

    https://trello.com/chuyennhatrongoithanhhung

    http://www.folkd.com/user/chuyennhatrongoithanhhung

    https://www.flickr.com/photos/186351652@N04/

     

    ReplyDelete
  20. TOPSoiCau.com - Soi cầu xổ số 3 miền, dự đoán kết quả XSMB, XSMT, XSMN chính xác. Soi cầu bạch thủ, song thủ, lô kép, lô xiên, dàn đề chuẩn tại TOPSoiCau


    Xem thêm: #topsoicau, #soicau, #soicauxsmb, #soicauxsmt, #soicauxsmn, #dudoanxsmb, #dudoanxsmt, #dudoanxsmn, #soicaurongbachkim, #soicauviet, #soicaulotto, #soicaulovip, #soicau3mien, #soicau7777, #soicau247, #soicau555, #soicau366, #soicauwap, #soicau568, #soicau24h, #soicau888, #soicau666, #soicauwin2888, #soicaukubet, #soicaukhongtu


    topsoicau

    topsoicau

    topsoicau

    topsoicau

    topsoicau


    Website: TOPSoiCau.com

    ReplyDelete
  21. Nice Blog!
    Know More About Quickbooks error h202? Get live support 24*7 from QuickBooks expert on tool-free Number.
    Click here to know How to fix Quickbooks error h202 Quickbooks error h202
    Dial for any tech support: 1-844-908-0801

    ReplyDelete
  22. Know what are the necessary things you should consider before enabling QuickBooks Direct Deposit Form. If you want to know about the procedure of activating direct deposit, contact at 1-855-6OO-4O6O.

    ReplyDelete
  23. TOPSoiCau - Chuyên trang SOI CẦU MB, MT, MN VIP 24h tốt nhất Việt Nam 247 cho anh em tham khảo, lấy số đẹp. Dự đoán kết quả xổ số 3 miền Bắc, Trung, Nam nhanh nhất hàng ngày.

    Xem thêm: #topsoicau, #soicau, #soicauxsmb, #soicauxsmt, #soicauxsmn, #dudoanxsmb, #dudoanxsmt, #dudoanxsmn, #soicaurongbachkim, #soicauviet, #soicaulotto, #soicaulovip, #soicau3mien, #soicau7777, #soicau247, #soicau555, #soicau366, #soicauwap, #soicau568, #soicau24h, #soicau888, #soicau666, #soicauwin2888, #soicaukubet, #soicaukhongtu


    https://twitter.com/topsoicau

    https://dev.to/topsoicau

    https://stocktwits.com/topsoicau

    https://flipboard.com/@topsoicau

    http://www.folkd.com/user/topsoicau



    Website: TOPSoiCau.com

    ReplyDelete
  24. Nice Blog!
    QuickBooks desktop payroll support phone number, available for fix your desktop issues and glitch.
    Dial QuickBooks desktop payroll support phone number 1-844-908-0801
    Dial for any tech support: 1-844-908-0801

    ReplyDelete
  25. KUBET - KU CASINO - Nhà cái hàng đầu khu vực châu Á. Cá cược Casino Online, lô đề, xóc đĩa, bóng đá, thể thao, game 3D. Nhận ngay ưu đãi lên tơi 558K khi đăng ký tài khoản KUCASINO, nạp tiền lần đầu.


    Xem thêm: #ku, #kubet, #kucasino, #kubetcasino, #soicaumb, #dande, #dudoanxsmb, #dudoanxsmn, #xsmb, #xsmn, #xsmt, #soicaumt, #soicaumn, #ku777, #ku888, #ku999, #thienhabet

    WEBSITE KUBET CHÍNH THỨC: kubet-kucasino.webflow.io

    Các chuyên mục chính tại KUBET

    KU

    Dàn đề

    Dự đoán XSMB

    Dự đoán XSMT

    Dự đoán XSMN

    ReplyDelete
  26. Struggling with QuickBooks Payroll Error 503? Fix it by dialling us at 1-855-6OO-4O6O. The error usually arrives due to improper installation of QuickBooks upgrading.

    ReplyDelete
  27. TOPSoiCau - Chuyên trang SOI CẦU MB, MT, MN VIP 24h tốt nhất Việt Nam 247 cho anh em tham khảo, lấy số đẹp. Dự đoán kết quả xổ số 3 miền Bắc, Trung, Nam nhanh nhất hàng ngày.

    Xem thêm: #topsoicau, #soicau, #soicauxsmb, #soicauxsmt, #soicauxsmn, #dudoanxsmb, #dudoanxsmt, #dudoanxsmn, #soicaurongbachkim, #soicauviet, #soicaulotto, #soicaulovip, #soicau3mien, #soicau7777, #soicau247, #soicau555, #soicau366, #soicauwap, #soicau568, #soicau24h, #soicau888, #soicau666, #soicauwin2888, #soicaukubet, #soicaukhongtu


    https://www.domestika.org/en/topsoicaucom

    https://sketchfab.com/topsoicau

    https://stocktwits.com/topsoicau

    https://vimeo.com/topsoicau/about

    https://gab.com/topsoicau



    Website: TOPSoiCau.com


    ReplyDelete
  28. Taxitaithanhhung.vn- công ty cung cấp dịch vụ chuyển nhà trọn gói tại Hải Phòng - chuyển nhà tại Hải Phòng - chuyển nhà Hải Phòng giá rẻ.

    https://medium.com/@vantaitthanhhung/chuyen-nha-tron-goi-hai-phong-taxitaithanhhung-vn-ed41a7a9c6f0

    https://sketchfab.com/chuyennhahaiphong

    https://infogram.com/dich-vu-chuyen-nha-tron-goi-hai-phong-1h7j4d83vp0x6nr?live

    https://stocktwits.com/chuyennhahaiphong

    https://www.domestika.org/en/chuyennhahaiphong

    Từ khóa chuyển nhà:
    #taxitaithanhhung
    #chuyennhahaiphong
    #chuyennhatrongoihaiphong
    #chuyennhataihaiphong
    #chuyennhahaiphonggiare
    #dichvuchuyennhahaiphong
    #vanchuyennhahaiphong
    #chuyennhahanoiuytin
    #dichvuchuyennhatrongoihaiphong

    Website chuyển nhà Thành Hưng: Taxitaithanhhung.vn


    ReplyDelete
  29. Are you having difficulty in verifying the email address in Cash App account? If trying numerous times, you are unable to handle these errors, you can always take help from the elite professionals who are ready to guide you at every step. Whenever you are in trouble, you can always call on Cash App helpline number which is always functional and the team can help you out at every step so that you can get rid of all type of errors completely from the roots in fraction of time and under the superlative guidance of the experts. Cash App Support Number

    ReplyDelete
  30. Are you having difficulty in dealing with email activation error in the Binance account/ With email activation, you could simply make some things easier for yourself and recovering password is one of them. If you have a major issues and you need guidance to handle that you can always call on Binance support number which is always functional and the team is ready to guide you at every step. You can connect with them for availing results that could be helpful in eliminating troubles immediately. Binance Helpline Number

    ReplyDelete
  31. Taxi tải Thành Hưng - Xe tải Thành Hưng - Vận tải Thành Hưng: Công ty cung cấp dịch vụ : Dịch vụ chuyển nhà trọn gói - Chuyển văn phòng trọn gói - Cho thuê kho bãi - Dịch vụ cho thuê kho xưởng tại Hà Nội - Hải Phòng - Quảng Ninh - Đà Nẵng - HCM


    https://about.me/taxitaithanhhung/

    https://www.pinterest.com/taxitaithanhhungvn/

    https://sites.google.com/view/taxitaithanhhungvn/

    https://muckrack.com/taxi-tai-thanh-hung

    https://sketchfab.com/taxitaithanhhung

    Từ khóa liên quan:
    #taxitaithanhhung #xetaithanhhung #vantaithanhhung #vanchuyenthanhhung #taxithanhhung #taithanhhung #xethanhhung #chuyennhathanhhung #chuyennhatrongoithanhhung #dichvuchuyennhatrongoihanoi #vanchuyennhahanoi #chuyennhahanoiuytin #chuyennhahanoi #chuyennhataihanoi #chuyennhatrongoihanoi #dichvuchuyennhahanoi #dichvuchuyenhathanhhung #chuyennhahanoigiare #chuyen nha #chuyennhatrongoi #chuyenvanphongtrongoi #chuyennhabacnam

    Website: Taxitaithanhhung.vn

    ReplyDelete
  32. Taxi tải Thành Hưng - Xe tải Thành Hưng - Vận tải Thành Hưng : Chúng tối chuyên cung cấp các Dịch vụ chuyển nhà trọn gói - Chuyển văn phòng trọn gói - Cho thuê kho bãi - Dịch vụ cho thuê kho xưởng tại Hà Nội - Hải Phòng - Quảng Ninh - Đà Nẵng - HCM


    https://twitter.com/taxitaihanoi

    https://gab.com/Taxitiathanhhung

    https://refind.com/taxitaithanhhung

    https://trello.com/taxitaithanhhungvn/activity

    http://www.folkd.com/user/taxitaithanhhungvn

    Từ khóa liên quan:
    #taxitaithanhhung #xetaithanhhung #vantaithanhhung #vanchuyenthanhhung #taxithanhhung #taithanhhung #xethanhhung #chuyennhathanhhung #chuyennhatrongoithanhhung #dichvuchuyennhatrongoihanoi #vanchuyennhahanoi #chuyennhahanoiuytin #chuyennhahanoi #chuyennhataihanoi #chuyennhatrongoihanoi #dichvuchuyennhahanoi #dichvuchuyenhathanhhung #chuyennhahanoigiare #chuyen nha #chuyennhatrongoi #chuyenvanphongtrongoi #chuyennhabacnam #vanchuyenbacnam

    Website: Taxitaithanhhung.vn


    ReplyDelete
  33. Its a great pleasure reading your post.Its full of information I am looking for and I love to post a comment that "The content of your post is awesome" Great work.
    DevOps Training in Chennai | DevOps Training in anna nagar | DevOps Training in omr | DevOps Training in porur | DevOps Training in tambaram | DevOps Training in velachery

    ReplyDelete
  34. Taxi tải Thành Hưng - Xe tải Thành Hưng - Vận tải Thành Hưng : chuyên cung cấp các Dịch vụ chuyển nhà trọn gói - Chuyển văn phòng trọn gói - Cho thuê kho bãi - Dịch vụ cho thuê kho xưởng - dịch vụ vận chuyển Bắc Trung Nam.

    https://ko-fi.com/taxitaithanhhung

    https://myspace.com/taxitaithanhhung

    https://ello.co/taxitaithanhhungvn

    https://www.scoop.it/u/tructia5288-gmail-com

    http://www.myfolio.com/taxitaithanhhungvn

    Từ khóa liên quan:
    #taxitaithanhhung #xetaithanhhung #vantaithanhhung #vanchuyenthanhhung #taxithanhhung #taithanhhung #xethanhhung #chuyennhathanhhung #chuyennhatrongoithanhhung #dichvuchuyennhatrongoihanoi #vanchuyennhahanoi #chuyennhahanoiuytin #chuyennhahanoi #chuyennhataihanoi #chuyennhatrongoihanoi #dichvuchuyennhahanoi #dichvuchuyenhathanhhung #chuyennhahanoigiare #chuyen nha #chuyennhatrongoi #chuyenvanphongtrongoi #chuyennhabacnam #vanchuyenbacnam

    Website: Taxitaithanhhung.vn

    ReplyDelete
  35. Taxi tải Thành Hưng - Xe tải Thành Hưng - Vận tải Thành Hưng: Công ty cung cấp dịch vụ : Dịch vụ chuyển nhà trọn gói Hà Nội - Chuyển văn phòng trọn gói Hà Nội - Cho thuê kho bãi - Vận chuyển nhà Bắc Trung Nam.


    https://taxitaithanhhungvn863122739.wordpress.com/

    http://chuyennhahanoi300.mystrikingly.com/

    https://taxitaithanhhungvn.weebly.com/

    http://taxitaithanhhungvn.over-blog.com/

    http://chuyennhahanoi300.mystrikingly.com/

    Từ khóa liên quan:
    #taxitaithanhhung #xetaithanhhung #vantaithanhhung #vanchuyenthanhhung #taxithanhhung #taithanhhung #xethanhhung #chuyennhathanhhung #chuyennhatrongoithanhhung #dichvuchuyennhatrongoihanoi #vanchuyennhahanoi #chuyennhahanoiuytin #chuyennhahanoi #chuyennhataihanoi #chuyennhatrongoihanoi #dichvuchuyennhahanoi #dichvuchuyenhathanhhung #chuyennhahanoigiare #chuyen nha #chuyennhatrongoi #chuyenvanphongtrongoi #chuyennhabacnam

    Website: Taxitaithanhhung.vn





    ReplyDelete
  36. Nice & Informative Blog ! Facing QuickBooks Error 15241? Don’t worry, dial us at 1(844)514-7111 for instant resolution of issues. QuickBooks Error 15241 or Could not initialize license Properties arrives while any of the company files is either missing or damaged.
    Fix QuickBooks Error code 15241

    ReplyDelete
  37. Worried about QuickBooks abort error ? if you are not able to fix QuickBooks error,get in touch with QuickBooks expert for instant solution.
    Click here to know how to fix QuickBooks abort error
    Dial on our toll-free QuickBooks Support Phone Number 1-844-908-0801

    ReplyDelete
  38. Get in touch with QuickBooks expert for instant solution, We live 24*7 live for Quick & fast service.
    Dial QuickBooks Helpline Number 1-844-908-0801

    ReplyDelete
  39. Taxi tải Thành Hưng - Xe tải Thành Hưng - Vận tải Thành Hưng : chuyên cung cấp các Dịch vụ chuyển nhà trọn gói - Chuyển văn phòng trọn gói - Cho thuê kho bãi - Dịch vụ cho thuê kho xưởng - dịch vụ vận chuyển Bắc Trung Nam.

    https://getpocket.com/@429T1Ae9g7453p4eWXd61b3d9ep5gd81427yc7rd9boeb2R9c9401a19vc5qa30Z

    https://www.instapaper.com/p/taxitaihanoi

    https://www.vingle.net/taxithanhhung

    https://www.deviantart.com/taxitaithanhhung

    https://visual.ly/users/taxitaithanhhung/

    Từ khóa liên quan:
    #taxitaithanhhung #xetaithanhhung #vantaithanhhung #vanchuyenthanhhung #taxithanhhung #taithanhhung #xethanhhung #chuyennhathanhhung #chuyennhatrongoithanhhung #dichvuchuyennhatrongoihanoi #vanchuyennhahanoi #chuyennhahanoiuytin #chuyennhahanoi #chuyennhataihanoi #chuyennhatrongoihanoi #dichvuchuyennhahanoi #dichvuchuyenhathanhhung #chuyennhahanoigiare #chuyen nha #chuyennhatrongoi #chuyenvanphongtrongoi #chuyennhabacnam #vanchuyenbacnam

    Website: Taxitaithanhhung.vn



    ReplyDelete
  40. Taxi tải Thành Hưng - Xe tải Thành Hưng - Vận tải Thành Hưng : chuyên cung cấp các Dịch vụ chuyển nhà trọn gói tại Hà Nội - Chuyển văn phòng trọn gói Hà Nội- Cho thuê kho bãi - Dịch vụ cho thuê kho xưởng - dịch vụ vận chuyển Bắc Trung Nam.

    https://www.diigo.com/user/taxitaithanhhung

    https://dashburst.com/taxitaithanhhung

    https://enetget.com/taxitaithanhhung

    https://www.zoimas.com/profile/taxitaithanhhung

    https://devpost.com/taxitaithanhhung

    Từ khóa liên quan:
    #taxitaithanhhung #xetaithanhhung #vantaithanhhung #vanchuyenthanhhung #taxithanhhung #taithanhhung #xethanhhung #chuyennhathanhhung #chuyennhatrongoithanhhung #dichvuchuyennhatrongoihanoi #vanchuyennhahanoi #chuyennhahanoiuytin #chuyennhahanoi #chuyennhataihanoi #chuyennhatrongoihanoi #dichvuchuyennhahanoi #dichvuchuyenhathanhhung #chuyennhahanoigiare #chuyen nha #chuyennhatrongoi #chuyenvanphongtrongoi #chuyennhabacnam #vanchuyenbacnam

    Website: Taxitaithanhhung.vn


    ReplyDelete
  41. Worried about error when updating quickbooks desktop or payroll?Get in touch with QuickBooks expert for instant solution.
    Click here to Know how to fix error when updating quickbooks desktop or payroll
    Dial for fix QuickBooks error or support on QuickBooks toll-free Number 1-844-908-0801

    ReplyDelete
  42. Facing any technical glitch in the QuickBooks? Give a call at QuickBooks Support Phone Number 1-833-325-0220. Our learned & certified QuickBooks experts available 24/7 to give assistance.

    ReplyDelete
  43. Taxi tải Thành Hưng - Xe tải Thành Hưng - Vận tải Thành Hưng : chuyên cung cấp các Dịch vụ chuyển nhà trọn gói - Chuyển văn phòng trọn gói - Cho thuê kho bãi - Dịch vụ cho thuê kho xưởng - dịch vụ vận chuyển Bắc Trung Nam.

    http://www.socialbookmarkssite.com/user/taxitaithanhhung

    https://labs.maarch.org/taxitaithanhhung

    https://gitlab.redox-os.org/taxitaithanhhung

    https://oneway.com/taxitaithanhhung

    https://redliberal.com/@taxitaithanhhung

    Từ khóa liên quan:
    #taxitaithanhhung #xetaithanhhung #vantaithanhhung #vanchuyenthanhhung #taxithanhhung #taithanhhung #xethanhhung #chuyennhathanhhung #chuyennhatrongoithanhhung #dichvuchuyennhatrongoihanoi #vanchuyennhahanoi #chuyennhahanoiuytin #chuyennhahanoi #chuyennhataihanoi #chuyennhatrongoihanoi #dichvuchuyennhahanoi #dichvuchuyenhathanhhung #chuyennhahanoigiare #chuyen nha #chuyennhatrongoi #chuyenvanphongtrongoi #chuyennhabacnam #vanchuyenbacnam

    Website: Taxitaithanhhung.vn



    ReplyDelete
  44. Taxi tải Thành Hưng - Xe tải Thành Hưng - Vận tải Thành Hưng : chuyên cung cấp các Dịch vụ chuyển nhà trọn gói tại Hà Nội - Chuyển văn phòng trọn gói Hà Nội- Cho thuê kho bãi - Dịch vụ cho thuê kho xưởng - dịch vụ vận chuyển Bắc Trung Nam.

    https://www.vietnamta.vn/taxitaithanhhung

    https://gamejolt.com/@taxitaithanhhun

    https://weheartit.com/taxitaithanhhungvn

    https://www.zoimas.com/profile/taxitaithanhhung

    https://sinblr.com/@taxitaithanhhung

    Từ khóa liên quan:
    #taxitaithanhhung #xetaithanhhung #vantaithanhhung #vanchuyenthanhhung #taxithanhhung #taithanhhung #xethanhhung #chuyennhathanhhung #chuyennhatrongoithanhhung #dichvuchuyennhatrongoihanoi #vanchuyennhahanoi #chuyennhahanoiuytin #chuyennhahanoi #chuyennhataihanoi #chuyennhatrongoihanoi #dichvuchuyennhahanoi #dichvuchuyenhathanhhung #chuyennhahanoigiare #chuyen nha #chuyennhatrongoi #chuyenvanphongtrongoi #chuyennhabacnam #vanchuyenbacnam

    Website: Taxitaithanhhung.vn

    ReplyDelete
  45. Well explained Informative Blog !
    Connect with us, at QuickBooks Toll Free Number 1-855-6OO-4O6O. Here, you can get effective solutions to resolve the technical snags in the Quickbooks software.

    ReplyDelete
  46. Nice Blog !
    Looking for QuickBooks Specialists? Your probe is now gonna end with this, dial 1-855-6OO-4O6O to connect with Intuit certified QuickBooks Proadvisors Support Phone Number 1-855-6OO-4O6O.

    ReplyDelete
  47. Directly connect to our Quickbooks Helpline Number 1-833-325-0220 and get your queries settled out there and then from our QB Payroll technicians.Read More: https://bit.ly/3gHf5m0

    ReplyDelete
  48. Taxi tải Thành Hưng - Xe tải Thành Hưng - Vận tải Thành Hưng : chuyên cung cấp các Dịch vụ chuyển nhà trọn gói - Chuyển văn phòng trọn gói - Cho thuê kho bãi - Dịch vụ cho thuê kho xưởng - dịch vụ vận chuyển Bắc Trung Nam.

    https://mastodon.cloud/@taxitaithanhhungvn

    https://qoto.org/@taxitaithanhhungvn

    https://mstdn.social/@taxitaithanhhungvn

    https://www.domestika.org/en/taxitaithanhhung

    https://dev.to/taxitaihanoi

    Từ khóa liên quan:
    #taxitaithanhhung #xetaithanhhung #vantaithanhhung #vanchuyenthanhhung #taxithanhhung #taithanhhung #xethanhhung #chuyennhathanhhung #chuyennhatrongoithanhhung #dichvuchuyennhatrongoihanoi #vanchuyennhahanoi #chuyennhahanoiuytin #chuyennhahanoi #chuyennhataihanoi #chuyennhatrongoihanoi #dichvuchuyennhahanoi #dichvuchuyenhathanhhung #chuyennhahanoigiare #chuyen nha #chuyennhatrongoi #chuyenvanphongtrongoi #chuyennhabacnam #vanchuyenbacnam

    Website: Taxitaithanhhung.vn


    ReplyDelete
  49. QuickBooks provide Premier Support for QuickBooks User to make QuickBooks more easy and fruitful.
    Dial QuickBooks customer service 1-844-908-0801

    ReplyDelete
  50. Thietkenhadepmoi.vn - công ty thiết kế nhà đẹp uy tín. Thiết kế nhà - thiết kế nhà đẹp mới - thiết kế thi công nhà đẹp - thiết kế xây dựng nhà đẹp - mẫu nhà đẹp mới. Tổng hợp các mẫu nhà mái thái đẹp - mẫu nhà phố đẹp - mẫu biệt thự đẹp sang trọng.
    Liên hệ ngay với công ty Thiết kế nhà đẹp mới để được tư vấn và báo giá miễn phí!

    Từ khóa thiết kế nhà đẹp mới :
    #thietkenhadepmoi #thietkenhadepmoivn #thietkennha #thietkennhadep #maunhadepmoi #thietkennhadepmoi #thietkennhauytin #maubietthudep #maunhamaithaidep #mauthietkenhadep #thietkexaydungnhadep #maunhaphodep #congtythietkenhadep #thietkethicongnhadep #thietkexaydungnhadep #maunhadepmoi #maunhamoi #xaydungnhadep #congtynhadep

    https://www.facebook.com/nhadepmoithietkexaydung/

    https://ello.co/thiekenhadepmoivn

    https://issuu.com/thiekenhadepmoivn

    https://www.behance.net/nhmipthitknhmi

    http://myfolio.com/thiekenhadepmoivn

    Website: Thietkenhadepmoi.vn

    ReplyDelete
  51. Thietkenhadepmoi.vn - công ty thiết kế nhà đẹp uy tín. Thiết kế nhà - thiết kế nhà đẹp mới - thiết kế thi công nhà đẹp - thiết kế xây dựng nhà đẹp - mẫu nhà đẹp mới. Tổng hợp các mẫu nhà mái thái đẹp - mẫu nhà phố đẹp - mẫu biệt thự đẹp sang trọng.
    Liên hệ ngay với công ty Thiết kế nhà đẹp mới để được tư vấn và báo giá miễn phí!

    Từ khóa thiết kế nhà đẹp mới :
    #thietkenhadepmoi #thietkenhadepmoivn #thietkennha #thietkennhadep #maunhadepmoi #thietkennhadepmoi #thietkennhauytin #maubietthudep #maunhamaithaidep #mauthietkenhadep #thietkexaydungnhadep #maunhaphodep #congtythietkenhadep #thietkethicongnhadep #thietkexaydungnhadep #maunhadepmoi #maunhamoi #xaydungnhadep #congtynhadep

    https://www.facebook.com/nhadepmoithietkexaydung/

    https://ello.co/thiekenhadepmoivn

    https://issuu.com/thiekenhadepmoivn

    https://www.behance.net/nhmipthitknhmi

    http://myfolio.com/thiekenhadepmoivn

    Website: Thietkenhadepmoi.vn

    ReplyDelete
  52. Putlocker - Putlockerc new site 2020 - Putlockerc new site | Putlocker new | Putlockerc.to where you can watch free movies online in HD quality.

    #putlocker
    #pulockerc
    #putlockerproxy
    #putlockers2
    #putlockerreddit
    #putlockerc.to
    #putlockerswebsite

    .
    .

    https://about.me/putlockercto

    https://500px.com/putlockercto

    https://putlockercto.blogspot.com/

    https://www.facebook.com/putlockercto

    https://www.flickr.com/people/putlockercto/



    Website: Putlockerc.to

    ReplyDelete
  53. Quickbooks Give 24*7 client Service Support To all Quickbooks Issues and Mistake fix with expert team are here for you and they are isnatnt resposn. dial +1-855-511-6911 Quickbooks enterorise support phone numbre

    ReplyDelete
  54. Nice Blog !
    Facing QuickBooks enterprise support Phone number Get it resolved by dialling our Qb experts at 1-855-511-6911.

    ReplyDelete
  55. Thietkenhadepmoi.vn - công ty thiết kế nhà đẹp uy tín. Thiết kế nhà - thiết kế nhà đẹp mới - thiết kế thi công nhà đẹp - thiết kế xây dựng nhà đẹp - mẫu nhà đẹp mới. Tổng hợp các mẫu nhà mái thái đẹp - mẫu nhà phố đẹp - mẫu biệt thự đẹp sang trọng.
    Liên hệ ngay với công ty Thiết kế nhà đẹp mới để được tư vấn và báo giá miễn phí!

    Từ khóa thiết kế nhà đẹp mới :
    #thietkenhadepmoi #thietkenhadepmoivn #thietkennha #thietkennhadep #maunhadepmoi #thietkennhadepmoi #thietkennhauytin #maubietthudep #maunhamaithaidep #mauthietkenhadep #thietkexaydungnhadep #maunhaphodep #congtythietkenhadep #thietkethicongnhadep #thietkexaydungnhadep #maunhadepmoi #maunhamoi #xaydungnhadep #congtynhadep

    https://www.pearltrees.com/thietkenhadepmoivn
    https://refind.com/thietkenhadepmoivn
    https://muckrack.com/thietkenhadepmoi-thietkenhadepmoivn
    https://mix.com/thietkenhadepmoivn
    hhttps://www.plurk.com/thietkenhadepmoivn

    Website: Thietkenhadepmoi.vn

    ReplyDelete